<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Chapter 12 Functions and Operators</title>
<link rel="stylesheet" href="mvl.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets + chunker.py v1.9.2" />
<link rel="start" href="index.html" title="{book-title}" />
<link rel="up" href="" title="" />
<link rel="prev" href="data-types.html" title="Chapter 11 Data Types" />
<link rel="next" href="sql-statements.html" title="Chapter 13 SQL Statements" />
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Chapter 12 Functions and Operators</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="data-types.html">Prev</a> </td>
<th width="60%" align="center"></th>
<td width="20%" align="right"> <a accesskey="n" href="sql-statements.html">Next</a></td>
</tr>
</table>
<hr>
</div>
<div class="chapter">
<div class="titlepage">
<div>
<div>
<h1 class="title"><a name="functions"></a>Chapter 12 Functions and Operators</h1>

</div>

</div>

</div>
<div class="toc">
<p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="functions.html#func-op-summary-ref">12.1 Function and Operator Reference</a></span></dt><dt><span class="section"><a href="functions.html#type-conversion">12.2 Type Conversion in Expression Evaluation</a></span></dt><dt><span class="section"><a href="functions.html#non-typed-operators">12.3 Operators</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#operator-precedence">12.3.1 Operator Precedence</a></span></dt><dt><span class="section"><a href="functions.html#comparison-operators">12.3.2 Comparison Functions and Operators</a></span></dt><dt><span class="section"><a href="functions.html#logical-operators">12.3.3 Logical Operators</a></span></dt><dt><span class="section"><a href="functions.html#assignment-operators">12.3.4 Assignment Operators</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#control-flow-functions">12.4 Control Flow Functions</a></span></dt><dt><span class="section"><a href="functions.html#numeric-functions">12.5 Numeric Functions and Operators</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#arithmetic-functions">12.5.1 Arithmetic Operators</a></span></dt><dt><span class="section"><a href="functions.html#mathematical-functions">12.5.2 Mathematical Functions</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#date-and-time-functions">12.6 Date and Time Functions</a></span></dt><dt><span class="section"><a href="functions.html#string-functions">12.7 String Functions and Operators</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#string-comparison-functions">12.7.1 String Comparison Functions and Operators</a></span></dt><dt><span class="section"><a href="functions.html#regexp">12.7.2 Regular Expressions</a></span></dt><dt><span class="section"><a href="functions.html#string-functions-charset">12.7.3 Character Set and Collation of Function Results</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#mysql-calendar">12.8 What Calendar Is Used By MySQL?</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-search">12.9 Full-Text Search Functions</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#fulltext-natural-language">12.9.1 Natural Language Full-Text Searches</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-boolean">12.9.2 Boolean Full-Text Searches</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-query-expansion">12.9.3 Full-Text Searches with Query Expansion</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-stopwords">12.9.4 Full-Text Stopwords</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-restrictions">12.9.5 Full-Text Restrictions</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-fine-tuning">12.9.6 Fine-Tuning MySQL Full-Text Search</a></span></dt><dt><span class="section"><a href="functions.html#full-text-adding-collation">12.9.7 Adding a Collation for Full-Text Indexing</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-search-ngram">12.9.8 ngram Full-Text Parser</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-search-mecab">12.9.9 MeCab Full-Text Parser Plugin</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#cast-functions">12.10 Cast Functions and Operators</a></span></dt><dt><span class="section"><a href="functions.html#xml-functions">12.11 XML Functions</a></span></dt><dt><span class="section"><a href="functions.html#bit-functions">12.12 Bit Functions and Operators</a></span></dt><dt><span class="section"><a href="functions.html#encryption-functions">12.13 Encryption and Compression Functions</a></span></dt><dt><span class="section"><a href="functions.html#locking-functions">12.14 Locking Functions</a></span></dt><dt><span class="section"><a href="functions.html#information-functions">12.15 Information Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-analysis-functions">12.16 Spatial Analysis Functions</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#spatial-function-reference">12.16.1 Spatial Function Reference</a></span></dt><dt><span class="section"><a href="functions.html#spatial-function-argument-handling">12.16.2 Argument Handling by Spatial Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-wkt-functions">12.16.3 Functions That Create Geometry Values from WKT Values</a></span></dt><dt><span class="section"><a href="functions.html#gis-wkb-functions">12.16.4 Functions That Create Geometry Values from WKB Values</a></span></dt><dt><span class="section"><a href="functions.html#gis-mysql-specific-functions">12.16.5 MySQL-Specific Functions That Create Geometry Values</a></span></dt><dt><span class="section"><a href="functions.html#gis-format-conversion-functions">12.16.6 Geometry Format Conversion Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-property-functions">12.16.7 Geometry Property Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-operator-functions">12.16.8 Spatial Operator Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-relation-functions">12.16.9 Functions That Test Spatial Relations Between Geometry Objects</a></span></dt><dt><span class="section"><a href="functions.html#spatial-geohash-functions">12.16.10 Spatial Geohash Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-geojson-functions">12.16.11 Spatial GeoJSON Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-convenience-functions">12.16.12 Spatial Convenience Functions</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#json-functions">12.17 JSON Functions</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#json-function-reference">12.17.1 JSON Function Reference</a></span></dt><dt><span class="section"><a href="functions.html#json-creation-functions">12.17.2 Functions That Create JSON Values</a></span></dt><dt><span class="section"><a href="functions.html#json-search-functions">12.17.3 Functions That Search JSON Values</a></span></dt><dt><span class="section"><a href="functions.html#json-modification-functions">12.17.4 Functions That Modify JSON Values</a></span></dt><dt><span class="section"><a href="functions.html#json-attribute-functions">12.17.5 Functions That Return JSON Value Attributes</a></span></dt><dt><span class="section"><a href="functions.html#json-table-functions">12.17.6 JSON Table Functions</a></span></dt><dt><span class="section"><a href="functions.html#json-validation-functions">12.17.7 JSON Schema Validation Functions</a></span></dt><dt><span class="section"><a href="functions.html#json-utility-functions">12.17.8 JSON Utility Functions</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#gtid-functions">12.18 Functions Used with Global Transaction Identifiers (GTIDs)</a></span></dt><dt><span class="section"><a href="functions.html#enterprise-encryption">12.19 MySQL Enterprise Encryption Functions</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#enterprise-encryption-installation">12.19.1 MySQL Enterprise Encryption Installation</a></span></dt><dt><span class="section"><a href="functions.html#enterprise-encryption-usage">12.19.2 MySQL Enterprise Encryption Usage and Examples</a></span></dt><dt><span class="section"><a href="functions.html#enterprise-encryption-function-reference">12.19.3 MySQL Enterprise Encryption Function Reference</a></span></dt><dt><span class="section"><a href="functions.html#enterprise-encryption-functions">12.19.4 MySQL Enterprise Encryption Function Descriptions</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#group-by-functions-and-modifiers">12.20 Aggregate (GROUP BY) Functions</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#group-by-functions">12.20.1 Aggregate (GROUP BY) Function Descriptions</a></span></dt><dt><span class="section"><a href="functions.html#group-by-modifiers">12.20.2 GROUP BY Modifiers</a></span></dt><dt><span class="section"><a href="functions.html#group-by-handling">12.20.3 MySQL Handling of GROUP BY</a></span></dt><dt><span class="section"><a href="functions.html#group-by-functional-dependence">12.20.4 Detection of Functional Dependence</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#window-functions">12.21 Window Functions</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#window-function-descriptions">12.21.1 Window Function Descriptions</a></span></dt><dt><span class="section"><a href="functions.html#window-functions-usage">12.21.2 Window Function Concepts and Syntax</a></span></dt><dt><span class="section"><a href="functions.html#window-functions-frames">12.21.3 Window Function Frame Specification</a></span></dt><dt><span class="section"><a href="functions.html#window-functions-named-windows">12.21.4 Named Windows</a></span></dt><dt><span class="section"><a href="functions.html#window-function-restrictions">12.21.5 Window Function Restrictions</a></span></dt></dl></dd><dt><span class="section"><a href="functions.html#performance-schema-functions">12.22 Performance Schema Functions</a></span></dt><dt><span class="section"><a href="functions.html#internal-functions">12.23 Internal Functions</a></span></dt><dt><span class="section"><a href="functions.html#miscellaneous-functions">12.24 Miscellaneous Functions</a></span></dt><dt><span class="section"><a href="functions.html#precision-math">12.25 Precision Math</a></span></dt><dd><dl><dt><span class="section"><a href="functions.html#precision-math-numbers">12.25.1 Types of Numeric Values</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-decimal-characteristics">12.25.2 DECIMAL Data Type Characteristics</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-expressions">12.25.3 Expression Handling</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-rounding">12.25.4 Rounding Behavior</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-examples">12.25.5 Precision Math Examples</a></span></dt></dl></dd></dl>
</div>
<a class="indexterm" name="idm46444334558656"></a><a class="indexterm" name="idm46444334557152"></a><a class="indexterm" name="idm46444334556080"></a><p>
    Expressions can be used at several points in
    <a class="link" href="glossary.html#glos_sql" title="SQL">SQL</a> statements, such as in the
    <code class="literal">ORDER BY</code> or <code class="literal">HAVING</code> clauses of
    <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statements, in the
    <code class="literal">WHERE</code> clause of a
    <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>,
    <a class="link" href="sql-statements.html#delete" title="13.2.2 DELETE Statement"><code class="literal">DELETE</code></a>, or
    <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement, or in
    <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
    statements. Expressions can be written using literal values, column
    values, <code class="literal">NULL</code>, built-in functions, stored
    functions, user-defined functions, and operators. This chapter
    describes the functions and operators that are permitted for writing
    expressions in MySQL. Instructions for writing stored functions and
    user-defined functions are given in
    <a class="xref" href="stored-objects.html#stored-routines" title="24.2 Using Stored Routines">Section 24.2, “Using Stored Routines”</a>, and
    <a class="xref" href="extending-mysql.html#adding-functions" title="29.4 Adding Functions to MySQL">Section 29.4, “Adding Functions to MySQL”</a>. See
    <a class="xref" href="language-structure.html#function-resolution" title="9.2.5 Function Name Parsing and Resolution">Section 9.2.5, “Function Name Parsing and Resolution”</a>, for the rules describing how
    the server interprets references to different kinds of functions.
  </p><p>
    An expression that contains <code class="literal">NULL</code> always produces
    a <code class="literal">NULL</code> value unless otherwise indicated in the
    documentation for a particular function or operator.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
      By default, there must be no whitespace between a function name
      and the parenthesis following it. This helps the MySQL parser
      distinguish between function calls and references to tables or
      columns that happen to have the same name as a function. However,
      spaces around function arguments are permitted.
</p>
</div>
<p>
    You can tell the MySQL server to accept spaces after function names
    by starting it with the
    <a class="link" href="server-administration.html#option_mysqld_sql-mode"><code class="option">--sql-mode=IGNORE_SPACE</code></a> option. (See
    <a class="xref" href="server-administration.html#sql-mode" title="5.1.11 Server SQL Modes">Section 5.1.11, “Server SQL Modes”</a>.) Individual client programs can request
    this behavior by using the <code class="literal">CLIENT_IGNORE_SPACE</code>
    option for <a class="link" href="connectors-apis.html#mysql-real-connect" title="28.7.6.54 mysql_real_connect()"><code class="literal">mysql_real_connect()</code></a>. In
    either case, all function names become reserved words.
  </p><p>
    For the sake of brevity, most examples in this chapter display the
    output from the <a class="link" href="programs.html#mysql" title="4.5.1 mysql — The MySQL Command-Line Client"><span class="command"><strong>mysql</strong></span></a> program in abbreviated
    form. Rather than showing examples in this format:
  </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MOD(29,9);</code></strong>
+-----------+
| mod(29,9) |
+-----------+
|         2 |
+-----------+
1 rows in set (0.00 sec)
</pre><p>
    This format is used instead:
  </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MOD(29,9);</code></strong>
        -&gt; 2
</pre>
<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="func-op-summary-ref"></a>12.1 Function and Operator Reference</h2>
</div>
</div>
</div>

<div class="table">
<a name="idm46444334527408"></a><p class="title"><b>Table 12.1 Functions and Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists all functions and operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a></td>
<td>
      Bitwise AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_greater-than"><code class="literal">&gt;</code></a></td>
<td>
      Greater than operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_right-shift"><code class="literal">&gt;&gt;</code></a></td>
<td>
      Right shift
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_greater-than-or-equal"><code class="literal">&gt;=</code></a></td>
<td>
      Greater than or equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_less-than"><code class="literal">&lt;</code></a></td>
<td>
      Less than operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-equal"><code class="literal">&lt;&gt;</code>, <code class="literal">!=</code></a></td>
<td>
      Not equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_left-shift"><code class="literal">&lt;&lt;</code></a></td>
<td>
      Left shift
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_less-than-or-equal"><code class="literal">&lt;=</code></a></td>
<td>
      Less than or equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_equal-to"><code class="literal">&lt;=&gt;</code></a></td>
<td>
      NULL-safe equal to operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_mod"><code class="literal">%</code>, <code class="literal">MOD</code></a></td>
<td>
      Modulo operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_times"><code class="literal">*</code></a></td>
<td>
      Multiplication operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a></td>
<td>
      Addition operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a></td>
<td>
      Minus operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_unary-minus"><code class="literal">-</code></a></td>
<td>
      Change the sign of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a></td>
<td>
      Return value from JSON column after evaluating path; equivalent to
      JSON_EXTRACT().
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_json-inline-path"><code class="literal">-&gt;&gt;</code></a></td>
<td>
      Return value from JSON column after evaluating path and unquoting
      the result; equivalent to JSON_UNQUOTE(JSON_EXTRACT()).
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_divide"><code class="literal">/</code></a></td>
<td>
      Division operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a></td>
<td>
      Assign a value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_assign-equal"><code class="literal">=</code></a></td>
<td>
      Assign a value (as part of a
      <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
      statement, or as part of the <code class="literal">SET</code> clause in an
      <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a></td>
<td>
      Equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-xor"><code class="literal">^</code></a></td>
<td>
      Bitwise XOR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_abs"><code class="literal">ABS()</code></a></td>
<td>
      Return the absolute value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_acos"><code class="literal">ACOS()</code></a></td>
<td>
      Return the arc cosine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_adddate"><code class="literal">ADDDATE()</code></a></td>
<td>
      Add time values (intervals) to a date value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_addtime"><code class="literal">ADDTIME()</code></a></td>
<td>
      Add time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a></td>
<td>
      Decrypt using AES
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a></td>
<td>
      Encrypt using AES
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_and"><code class="literal">AND</code>, <code class="literal">&amp;&amp;</code></a></td>
<td>
      Logical AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a></td>
<td>
      Suppress ONLY_FULL_GROUP_BY value rejection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ascii"><code class="literal">ASCII()</code></a></td>
<td>
      Return numeric value of left-most character
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asin"><code class="literal">ASIN()</code></a></td>
<td>
      Return the arc sine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-decrypt"><code class="literal">ASYMMETRIC_DECRYPT()</code></a></td>
<td>
      Decrypt ciphertext using private or public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-derive"><code class="literal">ASYMMETRIC_DERIVE()</code></a></td>
<td>
      Derive symmetric key from asymmetric keys
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a></td>
<td>
      Encrypt cleartext using private or public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-sign"><code class="literal">ASYMMETRIC_SIGN()</code></a></td>
<td>
      Generate signature from digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-verify"><code class="literal">ASYMMETRIC_VERIFY()</code></a></td>
<td>
      Verify that signature matches digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_atan"><code class="literal">ATAN()</code></a></td>
<td>
      Return the arc tangent
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_atan2"><code class="literal">ATAN2()</code>, <code class="literal">ATAN()</code></a></td>
<td>
      Return the arc tangent of the two arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_avg"><code class="literal">AVG()</code></a></td>
<td>
      Return the average value of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK()</code></a></td>
<td>
      Repeatedly execute an expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_between"><code class="literal">BETWEEN ... AND ...</code></a></td>
<td>
      Whether a value is within a range of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bin"><code class="literal">BIN()</code></a></td>
<td>
      Return a string containing binary representation of a number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a></td>
<td>
      Convert binary UUID to string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a></td>
<td>
      Cast a string to a binary string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a></td>
<td>
      Return bitwise AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-count"><code class="literal">BIT_COUNT()</code></a></td>
<td>
      Return the number of bits that are set
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-length"><code class="literal">BIT_LENGTH()</code></a></td>
<td>
      Return length of argument in bits
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a></td>
<td>
      Return bitwise OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a></td>
<td>
      Return bitwise XOR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_can-access-column"><code class="literal">CAN_ACCESS_COLUMN()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_can-access-database"><code class="literal">CAN_ACCESS_DATABASE()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_can-access-table"><code class="literal">CAN_ACCESS_TABLE()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_can-access-view"><code class="literal">CAN_ACCESS_VIEW()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_case"><code class="literal">CASE</code></a></td>
<td>
      Case operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a></td>
<td>
      Cast a value as a certain type
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ceil"><code class="literal">CEIL()</code></a></td>
<td>
      Return the smallest integer value not less than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ceiling"><code class="literal">CEILING()</code></a></td>
<td>
      Return the smallest integer value not less than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_char"><code class="literal">CHAR()</code></a></td>
<td>
      Return the character for each integer passed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_char-length"><code class="literal">CHAR_LENGTH()</code></a></td>
<td>
      Return number of characters in argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_character-length"><code class="literal">CHARACTER_LENGTH()</code></a></td>
<td>
      Synonym for CHAR_LENGTH()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_charset"><code class="literal">CHARSET()</code></a></td>
<td>
      Return the character set of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_coalesce"><code class="literal">COALESCE()</code></a></td>
<td>
      Return the first non-NULL argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_coercibility"><code class="literal">COERCIBILITY()</code></a></td>
<td>
      Return the collation coercibility value of the string argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_collation"><code class="literal">COLLATION()</code></a></td>
<td>
      Return the collation of the string argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_compress"><code class="literal">COMPRESS()</code></a></td>
<td>
      Return result as a binary string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a></td>
<td>
      Return concatenated string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_concat-ws"><code class="literal">CONCAT_WS()</code></a></td>
<td>
      Return concatenate with separator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_connection-id"><code class="literal">CONNECTION_ID()</code></a></td>
<td>
      Return the connection ID (thread ID) for the connection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_conv"><code class="literal">CONV()</code></a></td>
<td>
      Convert numbers between different number bases
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a></td>
<td>
      Cast a value as a certain type
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_convert-tz"><code class="literal">CONVERT_TZ()</code></a></td>
<td>
      Convert from one time zone to another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cos"><code class="literal">COS()</code></a></td>
<td>
      Return the cosine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cot"><code class="literal">COT()</code></a></td>
<td>
      Return the cotangent
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_count"><code class="literal">COUNT()</code></a></td>
<td>
      Return a count of the number of rows returned
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_count-distinct"><code class="literal">COUNT(DISTINCT)</code></a></td>
<td>
      Return the count of a number of different values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_crc32"><code class="literal">CRC32()</code></a></td>
<td>
      Compute a cyclic redundancy check value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a></td>
<td>
      Create private key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-asymmetric-pub-key"><code class="literal">CREATE_ASYMMETRIC_PUB_KEY()</code></a></td>
<td>
      Create public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a></td>
<td>
      Generate shared DH secret
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-digest"><code class="literal">CREATE_DIGEST()</code></a></td>
<td>
      Generate digest from string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cume-dist"><code class="literal">CUME_DIST()</code></a></td>
<td>
      Cumulative distribution value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_curdate"><code class="literal">CURDATE()</code></a></td>
<td>
      Return the current date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-date"><code class="literal">CURRENT_DATE()</code>, <code class="literal">CURRENT_DATE</code></a></td>
<td>
      Synonyms for CURDATE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-role"><code class="literal">CURRENT_ROLE()</code></a></td>
<td>
      Return the current active roles
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-time"><code class="literal">CURRENT_TIME()</code>, <code class="literal">CURRENT_TIME</code></a></td>
<td>
      Synonyms for CURTIME()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-timestamp"><code class="literal">CURRENT_TIMESTAMP()</code>, <code class="literal">CURRENT_TIMESTAMP</code></a></td>
<td>
      Synonyms for NOW()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code>, <code class="literal">CURRENT_USER</code></a></td>
<td>
      The authenticated user name and host name
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_curtime"><code class="literal">CURTIME()</code></a></td>
<td>
      Return the current time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_database"><code class="literal">DATABASE()</code></a></td>
<td>
      Return the default (current) database name
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date"><code class="literal">DATE()</code></a></td>
<td>
      Extract the date part of a date or datetime expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a></td>
<td>
      Add time values (intervals) to a date value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a></td>
<td>
      Format date as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB()</code></a></td>
<td>
      Subtract a time value (interval) from a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_datediff"><code class="literal">DATEDIFF()</code></a></td>
<td>
      Subtract two dates
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_day"><code class="literal">DAY()</code></a></td>
<td>
      Synonym for DAYOFMONTH()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayname"><code class="literal">DAYNAME()</code></a></td>
<td>
      Return the name of the weekday
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayofmonth"><code class="literal">DAYOFMONTH()</code></a></td>
<td>
      Return the day of the month (0-31)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayofweek"><code class="literal">DAYOFWEEK()</code></a></td>
<td>
      Return the weekday index of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayofyear"><code class="literal">DAYOFYEAR()</code></a></td>
<td>
      Return the day of the year (1-366)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_default"><code class="literal">DEFAULT()</code></a></td>
<td>
      Return the default value for a table column
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_degrees"><code class="literal">DEGREES()</code></a></td>
<td>
      Convert radians to degrees
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dense-rank"><code class="literal">DENSE_RANK()</code></a></td>
<td>
      Rank of current row within its partition, without gaps
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_div"><code class="literal">DIV</code></a></td>
<td>
      Integer division
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_elt"><code class="literal">ELT()</code></a></td>
<td>
      Return string at index number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_exp"><code class="literal">EXP()</code></a></td>
<td>
      Raise to the power of
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_export-set"><code class="literal">EXPORT_SET()</code></a></td>
<td>
      Return a string such that for every bit set in the value bits, you
      get an on string and for every unset bit, you get an off string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_extract"><code class="literal">EXTRACT()</code></a></td>
<td>
      Extract part of a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a></td>
<td>
      Extract a value from an XML string using XPath notation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_field"><code class="literal">FIELD()</code></a></td>
<td>
      Index (position) of first argument in subsequent arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_find-in-set"><code class="literal">FIND_IN_SET()</code></a></td>
<td>
      Index (position) of first argument within second argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_first-value"><code class="literal">FIRST_VALUE()</code></a></td>
<td>
      Value of argument from first row of window frame
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_floor"><code class="literal">FLOOR()</code></a></td>
<td>
      Return the largest integer value not greater than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_format"><code class="literal">FORMAT()</code></a></td>
<td>
      Return a number formatted to specified number of decimal places
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_format-bytes"><code class="literal">FORMAT_BYTES()</code></a> (introduced 8.0.16)</td>
<td>
      Convert byte count to value with units
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_format-pico-time"><code class="literal">FORMAT_PICO_TIME()</code></a> (introduced 8.0.16)</td>
<td>
      Convert time in picoseconds to value with units
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a></td>
<td>
      For a SELECT with a LIMIT clause, the number of rows that would be
      returned were there no LIMIT clause
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_from-base64"><code class="literal">FROM_BASE64()</code></a></td>
<td>
      Decode base64 encoded string and return result
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_from-days"><code class="literal">FROM_DAYS()</code></a></td>
<td>
      Convert a day number to a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_from-unixtime"><code class="literal">FROM_UNIXTIME()</code></a></td>
<td>
      Format Unix timestamp as a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a></td>
<td>
      Construct geometry collection from geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection()</code></a></td>
<td>
      Construct geometry collection from geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-dd-column-privileges"><code class="literal">GET_DD_COLUMN_PRIVILEGES()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-dd-create-options"><code class="literal">GET_DD_CREATE_OPTIONS()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-dd-index-sub-part-length"><code class="literal">GET_DD_INDEX_SUB_PART_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT()</code></a></td>
<td>
      Return a date format string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a></td>
<td>
      Get a named lock
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_greatest"><code class="literal">GREATEST()</code></a></td>
<td>
      Return the largest argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_group-concat"><code class="literal">GROUP_CONCAT()</code></a></td>
<td>
      Return a concatenated string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a></td>
<td>
      Distinguish super-aggregate ROLLUP rows from regular rows
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_gtid-subset"><code class="literal">GTID_SUBSET()</code></a></td>
<td>
      Return true if all GTIDs in subset are also in set; otherwise
      false.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_gtid-subtract"><code class="literal">GTID_SUBTRACT()</code></a></td>
<td>
      Return all GTIDs in set that are not in subset.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a></td>
<td>
      Hexadecimal representation of decimal or string value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_hour"><code class="literal">HOUR()</code></a></td>
<td>
      Extract the hour
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_icu-version"><code class="literal">ICU_VERSION()</code></a></td>
<td>
      ICU library version
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_if"><code class="literal">IF()</code></a></td>
<td>
      If/else construct
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ifnull"><code class="literal">IFNULL()</code></a></td>
<td>
      Null if/else construct
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_in"><code class="literal">IN()</code></a></td>
<td>
      Whether a value is within a set of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a></td>
<td>
      Return the numeric value of an IP address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet-ntoa"><code class="literal">INET_NTOA()</code></a></td>
<td>
      Return the IP address from a numeric value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a></td>
<td>
      Return the numeric value of an IPv6 address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet6-ntoa"><code class="literal">INET6_NTOA()</code></a></td>
<td>
      Return the IPv6 address from a numeric value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_insert"><code class="literal">INSERT()</code></a></td>
<td>
      Insert substring at specified position up to specified number of
      characters
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_instr"><code class="literal">INSTR()</code></a></td>
<td>
      Return the index of the first occurrence of substring
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-auto-increment"><code class="literal">INTERNAL_AUTO_INCREMENT()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-avg-row-length"><code class="literal">INTERNAL_AVG_ROW_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-check-time"><code class="literal">INTERNAL_CHECK_TIME()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-checksum"><code class="literal">INTERNAL_CHECKSUM()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-data-free"><code class="literal">INTERNAL_DATA_FREE()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-data-length"><code class="literal">INTERNAL_DATA_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-dd-char-length"><code class="literal">INTERNAL_DD_CHAR_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-comment-or-error"><code class="literal">INTERNAL_GET_COMMENT_OR_ERROR()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-enabled-role-json"><code class="literal">INTERNAL_GET_ENABLED_ROLE_JSON()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-hostname"><code class="literal">INTERNAL_GET_HOSTNAME()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-username"><code class="literal">INTERNAL_GET_USERNAME()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-view-warning-or-error"><code class="literal">INTERNAL_GET_VIEW_WARNING_OR_ERROR()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-index-column-cardinality"><code class="literal">INTERNAL_INDEX_COLUMN_CARDINALITY()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-index-length"><code class="literal">INTERNAL_INDEX_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-is-enabled-role"><code class="literal">INTERNAL_IS_ENABLED_ROLE()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-is-mandatory-role"><code class="literal">INTERNAL_IS_MANDATORY_ROLE()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-keys-disabled"><code class="literal">INTERNAL_KEYS_DISABLED()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-max-data-length"><code class="literal">INTERNAL_MAX_DATA_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-table-rows"><code class="literal">INTERNAL_TABLE_ROWS()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-update-time"><code class="literal">INTERNAL_UPDATE_TIME()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_interval"><code class="literal">INTERVAL()</code></a></td>
<td>
      Return the index of the argument that is less than the first
      argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is"><code class="literal">IS</code></a></td>
<td>
      Test a value against a boolean
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-free-lock"><code class="literal">IS_FREE_LOCK()</code></a></td>
<td>
      Whether the named lock is free
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv4"><code class="literal">IS_IPV4()</code></a></td>
<td>
      Whether argument is an IPv4 address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv4-compat"><code class="literal">IS_IPV4_COMPAT()</code></a></td>
<td>
      Whether argument is an IPv4-compatible address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv4-mapped"><code class="literal">IS_IPV4_MAPPED()</code></a></td>
<td>
      Whether argument is an IPv4-mapped address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv6"><code class="literal">IS_IPV6()</code></a></td>
<td>
      Whether argument is an IPv6 address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-not"><code class="literal">IS NOT</code></a></td>
<td>
      Test a value against a boolean
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-not-null"><code class="literal">IS NOT NULL</code></a></td>
<td>
      NOT NULL value test
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-null"><code class="literal">IS NULL</code></a></td>
<td>
      NULL value test
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-used-lock"><code class="literal">IS_USED_LOCK()</code></a></td>
<td>
      Whether the named lock is in use; return connection identifier if
      true
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-uuid"><code class="literal">IS_UUID()</code></a></td>
<td>
      Whether argument is a valid UUID
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_isnull"><code class="literal">ISNULL()</code></a></td>
<td>
      Test whether the argument is NULL
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-array"><code class="literal">JSON_ARRAY()</code></a></td>
<td>
      Create JSON array
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-array-append"><code class="literal">JSON_ARRAY_APPEND()</code></a></td>
<td>
      Append data to JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-array-insert"><code class="literal">JSON_ARRAY_INSERT()</code></a></td>
<td>
      Insert into JSON array
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-arrayagg"><code class="literal">JSON_ARRAYAGG()</code></a></td>
<td>
      Return result set as a single JSON array
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-contains"><code class="literal">JSON_CONTAINS()</code></a></td>
<td>
      Whether JSON document contains specific object at path
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-contains-path"><code class="literal">JSON_CONTAINS_PATH()</code></a></td>
<td>
      Whether JSON document contains any data at path
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-depth"><code class="literal">JSON_DEPTH()</code></a></td>
<td>
      Maximum depth of JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-extract"><code class="literal">JSON_EXTRACT()</code></a></td>
<td>
      Return data from JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-insert"><code class="literal">JSON_INSERT()</code></a></td>
<td>
      Insert data into JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-keys"><code class="literal">JSON_KEYS()</code></a></td>
<td>
      Array of keys from JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-length"><code class="literal">JSON_LENGTH()</code></a></td>
<td>
      Number of elements in JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-merge"><code class="literal">JSON_MERGE()</code></a> (deprecated)</td>
<td>
      Merge JSON documents, preserving duplicate keys. Deprecated
      synonym for JSON_MERGE_PRESERVE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-merge-patch"><code class="literal">JSON_MERGE_PATCH()</code></a></td>
<td>
      Merge JSON documents, replacing values of duplicate keys
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-merge-preserve"><code class="literal">JSON_MERGE_PRESERVE()</code></a></td>
<td>
      Merge JSON documents, preserving duplicate keys
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-object"><code class="literal">JSON_OBJECT()</code></a></td>
<td>
      Create JSON object
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-objectagg"><code class="literal">JSON_OBJECTAGG()</code></a></td>
<td>
      Return result set as a single JSON object
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-overlaps"><code class="literal">JSON_OVERLAPS()</code></a> (introduced 8.0.17)</td>
<td>
      Compares two JSON documents, returns TRUE (1) if these have any
      key-value pairs or array elements in common, otherwise FALSE (0)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-pretty"><code class="literal">JSON_PRETTY()</code></a></td>
<td>
      Print a JSON document in human-readable format
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-quote"><code class="literal">JSON_QUOTE()</code></a></td>
<td>
      Quote JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-remove"><code class="literal">JSON_REMOVE()</code></a></td>
<td>
      Remove data from JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a></td>
<td>
      Replace values in JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-schema-valid"><code class="literal">JSON_SCHEMA_VALID()</code></a> (introduced 8.0.17)</td>
<td>
      Validate JSON document against JSON schema; returns TRUE/1 if
      document validates against schema, or FALSE/0 if it does not
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-schema-validation-report"><code class="literal">JSON_SCHEMA_VALIDATION_REPORT()</code></a> (introduced 8.0.17)</td>
<td>
      Validate JSON document against JSON schema; returns report in JSON
      format on outcome on validation including success or failure and
      reasons for failure
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-search"><code class="literal">JSON_SEARCH()</code></a></td>
<td>
      Path to value within JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a></td>
<td>
      Insert data into JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-storage-free"><code class="literal">JSON_STORAGE_FREE()</code></a></td>
<td>
      Freed space within binary representation of JSON column value
      following partial update
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-storage-size"><code class="literal">JSON_STORAGE_SIZE()</code></a></td>
<td>
      Space used for storage of binary representation of a JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-table"><code class="literal">JSON_TABLE()</code></a></td>
<td>
      Return data from a JSON expression as a relational table
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-type"><code class="literal">JSON_TYPE()</code></a></td>
<td>
      Type of JSON value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-unquote"><code class="literal">JSON_UNQUOTE()</code></a></td>
<td>
      Unquote JSON value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-valid"><code class="literal">JSON_VALID()</code></a></td>
<td>
      Whether JSON value is valid
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-value"><code class="literal">JSON_VALUE()</code></a> (introduced 8.0.21)</td>
<td>
      Extract value from JSON document at location pointed to by path
      provided; return this value as VARCHAR(512) or specified type
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a></td>
<td>
      Value of argument from row lagging current row within partition
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_last-day"><code class="literal">LAST_DAY</code></a></td>
<td>
      Return the last day of the month for the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a></td>
<td>
      Value of the AUTOINCREMENT column for the last INSERT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_last-value"><code class="literal">LAST_VALUE()</code></a></td>
<td>
      Value of argument from last row of window frame
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lcase"><code class="literal">LCASE()</code></a></td>
<td>
      Synonym for LOWER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a></td>
<td>
      Value of argument from row leading current row within partition
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_least"><code class="literal">LEAST()</code></a></td>
<td>
      Return the smallest argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_left"><code class="literal">LEFT()</code></a></td>
<td>
      Return the leftmost number of characters as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_length"><code class="literal">LENGTH()</code></a></td>
<td>
      Return the length of a string in bytes
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a></td>
<td>
      Simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_linestring"><code class="literal">LineString()</code></a></td>
<td>
      Construct LineString from Point values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ln"><code class="literal">LN()</code></a></td>
<td>
      Return the natural logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_load-file"><code class="literal">LOAD_FILE()</code></a></td>
<td>
      Load the named file
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_localtime"><code class="literal">LOCALTIME()</code>, <code class="literal">LOCALTIME</code></a></td>
<td>
      Synonym for NOW()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_localtimestamp"><code class="literal">LOCALTIMESTAMP</code>, <code class="literal">LOCALTIMESTAMP()</code></a></td>
<td>
      Synonym for NOW()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_locate"><code class="literal">LOCATE()</code></a></td>
<td>
      Return the position of the first occurrence of substring
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log"><code class="literal">LOG()</code></a></td>
<td>
      Return the natural logarithm of the first argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log10"><code class="literal">LOG10()</code></a></td>
<td>
      Return the base-10 logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log2"><code class="literal">LOG2()</code></a></td>
<td>
      Return the base-2 logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a></td>
<td>
      Return the argument in lowercase
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lpad"><code class="literal">LPAD()</code></a></td>
<td>
      Return the string argument, left-padded with the specified string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ltrim"><code class="literal">LTRIM()</code></a></td>
<td>
      Remove leading spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_make-set"><code class="literal">MAKE_SET()</code></a></td>
<td>
      Return a set of comma-separated strings that have the
      corresponding bit in bits set
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_makedate"><code class="literal">MAKEDATE()</code></a></td>
<td>
      Create a date from the year and day of year
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_maketime"><code class="literal">MAKETIME()</code></a></td>
<td>
      Create time from hour, minute, second
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_master-pos-wait"><code class="literal">MASTER_POS_WAIT()</code></a></td>
<td>
      Block until the slave has read and applied all updates up to the
      specified position
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_match"><code class="literal">MATCH</code></a></td>
<td>
      Perform full-text search
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_max"><code class="literal">MAX()</code></a></td>
<td>
      Return the maximum value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrcontains"><code class="literal">MBRContains()</code></a></td>
<td>
      Whether MBR of one geometry contains MBR of another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrcoveredby"><code class="literal">MBRCoveredBy()</code></a></td>
<td>
      Whether one MBR is covered by another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrcovers"><code class="literal">MBRCovers()</code></a></td>
<td>
      Whether one MBR covers another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrdisjoint"><code class="literal">MBRDisjoint()</code></a></td>
<td>
      Whether MBRs of two geometries are disjoint
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrequals"><code class="literal">MBREquals()</code></a></td>
<td>
      Whether MBRs of two geometries are equal
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrintersects"><code class="literal">MBRIntersects()</code></a></td>
<td>
      Whether MBRs of two geometries intersect
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbroverlaps"><code class="literal">MBROverlaps()</code></a></td>
<td>
      Whether MBRs of two geometries overlap
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrtouches"><code class="literal">MBRTouches()</code></a></td>
<td>
      Whether MBRs of two geometries touch
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrwithin"><code class="literal">MBRWithin()</code></a></td>
<td>
      Whether MBR of one geometry is within MBR of another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a></td>
<td>
      Calculate MD5 checksum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_member-of"><code class="literal">MEMBER OF()</code></a> (introduced 8.0.17)</td>
<td>
      Returns true (1) if first operand matches any element of JSON
      array passed as second operand, otherwise returns false (0)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_microsecond"><code class="literal">MICROSECOND()</code></a></td>
<td>
      Return the microseconds from argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mid"><code class="literal">MID()</code></a></td>
<td>
      Return a substring starting from the specified position
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_min"><code class="literal">MIN()</code></a></td>
<td>
      Return the minimum value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_minute"><code class="literal">MINUTE()</code></a></td>
<td>
      Return the minute from the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mod"><code class="literal">MOD()</code></a></td>
<td>
      Return the remainder
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_month"><code class="literal">MONTH()</code></a></td>
<td>
      Return the month from the date passed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_monthname"><code class="literal">MONTHNAME()</code></a></td>
<td>
      Return the name of the month
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_multilinestring"><code class="literal">MultiLineString()</code></a></td>
<td>
      Contruct MultiLineString from LineString values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_multipoint"><code class="literal">MultiPoint()</code></a></td>
<td>
      Construct MultiPoint from Point values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_multipolygon"><code class="literal">MultiPolygon()</code></a></td>
<td>
      Construct MultiPolygon from Polygon values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_name-const"><code class="literal">NAME_CONST()</code></a></td>
<td>
      Cause the column to have the given name
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not"><code class="literal">NOT</code>, <code class="literal">!</code></a></td>
<td>
      Negates value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-between"><code class="literal">NOT BETWEEN ... AND ...</code></a></td>
<td>
      Whether a value is not within a range of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-in"><code class="literal">NOT IN()</code></a></td>
<td>
      Whether a value is not within a set of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-like"><code class="literal">NOT LIKE</code></a></td>
<td>
      Negation of simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-regexp"><code class="literal">NOT REGEXP</code></a></td>
<td>
      Negation of REGEXP
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a></td>
<td>
      Return the current date and time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_nth-value"><code class="literal">NTH_VALUE()</code></a></td>
<td>
      Value of argument from N-th row of window frame
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ntile"><code class="literal">NTILE()</code></a></td>
<td>
      Bucket number of current row within its partition.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_nullif"><code class="literal">NULLIF()</code></a></td>
<td>
      Return NULL if expr1 = expr2
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_oct"><code class="literal">OCT()</code></a></td>
<td>
      Return a string containing octal representation of a number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_octet-length"><code class="literal">OCTET_LENGTH()</code></a></td>
<td>
      Synonym for LENGTH()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_or"><code class="literal">OR</code>, <code class="literal">||</code></a></td>
<td>
      Logical OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ord"><code class="literal">ORD()</code></a></td>
<td>
      Return character code for leftmost character of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_percent-rank"><code class="literal">PERCENT_RANK()</code></a></td>
<td>
      Percentage rank value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_period-add"><code class="literal">PERIOD_ADD()</code></a></td>
<td>
      Add a period to a year-month
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_period-diff"><code class="literal">PERIOD_DIFF()</code></a></td>
<td>
      Return the number of months between periods
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_pi"><code class="literal">PI()</code></a></td>
<td>
      Return the value of pi
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_point"><code class="literal">Point()</code></a></td>
<td>
      Construct Point from coordinates
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_polygon"><code class="literal">Polygon()</code></a></td>
<td>
      Construct Polygon from LineString arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_position"><code class="literal">POSITION()</code></a></td>
<td>
      Synonym for LOCATE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_pow"><code class="literal">POW()</code></a></td>
<td>
      Return the argument raised to the specified power
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_power"><code class="literal">POWER()</code></a></td>
<td>
      Return the argument raised to the specified power
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ps-current-thread-id"><code class="literal">PS_CURRENT_THREAD_ID()</code></a> (introduced 8.0.16)</td>
<td>
      Performance Schema thread ID for current thread
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> (introduced 8.0.16)</td>
<td>
      Performance Schema thread ID for given thread
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_quarter"><code class="literal">QUARTER()</code></a></td>
<td>
      Return the quarter from a date argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_quote"><code class="literal">QUOTE()</code></a></td>
<td>
      Escape the argument for use in an SQL statement
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_radians"><code class="literal">RADIANS()</code></a></td>
<td>
      Return argument converted to radians
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a></td>
<td>
      Return a random floating-point value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_random-bytes"><code class="literal">RANDOM_BYTES()</code></a></td>
<td>
      Return a random byte vector
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a></td>
<td>
      Rank of current row within its partition, with gaps
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">REGEXP</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-instr"><code class="literal">REGEXP_INSTR()</code></a></td>
<td>
      Starting index of substring matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-replace"><code class="literal">REGEXP_REPLACE()</code></a></td>
<td>
      Replace substrings matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-substr"><code class="literal">REGEXP_SUBSTR()</code></a></td>
<td>
      Return substring matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_release-all-locks"><code class="literal">RELEASE_ALL_LOCKS()</code></a></td>
<td>
      Release all current named locks
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_release-lock"><code class="literal">RELEASE_LOCK()</code></a></td>
<td>
      Release the named lock
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_repeat"><code class="literal">REPEAT()</code></a></td>
<td>
      Repeat a string the specified number of times
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_replace"><code class="literal">REPLACE()</code></a></td>
<td>
      Replace occurrences of a specified string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_reverse"><code class="literal">REVERSE()</code></a></td>
<td>
      Reverse the characters in a string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_right"><code class="literal">RIGHT()</code></a></td>
<td>
      Return the specified rightmost number of characters
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">RLIKE</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_roles-graphml"><code class="literal">ROLES_GRAPHML()</code></a></td>
<td>
      Return a GraphML document representing memory role subgraphs
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a></td>
<td>
      Round the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_row-count"><code class="literal">ROW_COUNT()</code></a></td>
<td>
      The number of rows updated
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a></td>
<td>
      Number of current row within its partition
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rpad"><code class="literal">RPAD()</code></a></td>
<td>
      Append string the specified number of times
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rtrim"><code class="literal">RTRIM()</code></a></td>
<td>
      Remove trailing spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_schema"><code class="literal">SCHEMA()</code></a></td>
<td>
      Synonym for DATABASE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sec-to-time"><code class="literal">SEC_TO_TIME()</code></a></td>
<td>
      Converts seconds to 'hh:mm:ss' format
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_second"><code class="literal">SECOND()</code></a></td>
<td>
      Return the second (0-59)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_session-user"><code class="literal">SESSION_USER()</code></a></td>
<td>
      Synonym for USER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code>, <code class="literal">SHA()</code></a></td>
<td>
      Calculate an SHA-1 160-bit checksum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sha2"><code class="literal">SHA2()</code></a></td>
<td>
      Calculate an SHA-2 checksum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sign"><code class="literal">SIGN()</code></a></td>
<td>
      Return the sign of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sin"><code class="literal">SIN()</code></a></td>
<td>
      Return the sine of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sleep"><code class="literal">SLEEP()</code></a></td>
<td>
      Sleep for a number of seconds
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_soundex"><code class="literal">SOUNDEX()</code></a></td>
<td>
      Return a soundex string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_sounds-like"><code class="literal">SOUNDS LIKE</code></a></td>
<td>
      Compare sounds
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_space"><code class="literal">SPACE()</code></a></td>
<td>
      Return a string of the specified number of spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sqrt"><code class="literal">SQRT()</code></a></td>
<td>
      Return the square root of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-area"><code class="literal">ST_Area()</code></a></td>
<td>
      Return Polygon or MultiPolygon area
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-asbinary"><code class="literal">ST_AsBinary()</code>, <code class="literal">ST_AsWKB()</code></a></td>
<td>
      Convert from internal geometry format to WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-asgeojson"><code class="literal">ST_AsGeoJSON()</code></a></td>
<td>
      Generate GeoJSON object from geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsText()</code>, <code class="literal">ST_AsWKT()</code></a></td>
<td>
      Convert from internal geometry format to WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a></td>
<td>
      Return geometry of points within given distance from geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy()</code></a></td>
<td>
      Produce strategy option for ST_Buffer()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-centroid"><code class="literal">ST_Centroid()</code></a></td>
<td>
      Return centroid as a point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-contains"><code class="literal">ST_Contains()</code></a></td>
<td>
      Whether one geometry contains another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-convexhull"><code class="literal">ST_ConvexHull()</code></a></td>
<td>
      Return convex hull of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-crosses"><code class="literal">ST_Crosses()</code></a></td>
<td>
      Whether one geometry crosses another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-difference"><code class="literal">ST_Difference()</code></a></td>
<td>
      Return point set difference of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-dimension"><code class="literal">ST_Dimension()</code></a></td>
<td>
      Dimension of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-disjoint"><code class="literal">ST_Disjoint()</code></a></td>
<td>
      Whether one geometry is disjoint from another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a></td>
<td>
      The distance of one geometry from another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-distance-sphere"><code class="literal">ST_Distance_Sphere()</code></a></td>
<td>
      Minimum distance on earth between two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-endpoint"><code class="literal">ST_EndPoint()</code></a></td>
<td>
      End Point of LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-envelope"><code class="literal">ST_Envelope()</code></a></td>
<td>
      Return MBR of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-equals"><code class="literal">ST_Equals()</code></a></td>
<td>
      Whether one geometry is equal to another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-exteriorring"><code class="literal">ST_ExteriorRing()</code></a></td>
<td>
      Return exterior ring of Polygon
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geohash"><code class="literal">ST_GeoHash()</code></a></td>
<td>
      Produce a geohash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomcollfromtext"><code class="literal">ST_GeomCollFromText()</code>, <code class="literal">ST_GeometryCollectionFromText()</code>, <code class="literal">ST_GeomCollFromTxt()</code></a></td>
<td>
      Return geometry collection from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomcollfromwkb"><code class="literal">ST_GeomCollFromWKB()</code>, <code class="literal">ST_GeometryCollectionFromWKB()</code></a></td>
<td>
      Return geometry collection from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geometryn"><code class="literal">ST_GeometryN()</code></a></td>
<td>
      Return N-th geometry from geometry collection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geometrytype"><code class="literal">ST_GeometryType()</code></a></td>
<td>
      Return name of geometry type
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomfromgeojson"><code class="literal">ST_GeomFromGeoJSON()</code></a></td>
<td>
      Generate geometry from GeoJSON object
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code>, <code class="literal">ST_GeometryFromText()</code></a></td>
<td>
      Return geometry from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomfromwkb"><code class="literal">ST_GeomFromWKB()</code>, <code class="literal">ST_GeometryFromWKB()</code></a></td>
<td>
      Return geometry from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-interiorringn"><code class="literal">ST_InteriorRingN()</code></a></td>
<td>
      Return N-th interior ring of Polygon
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-intersection"><code class="literal">ST_Intersection()</code></a></td>
<td>
      Return point set intersection of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-intersects"><code class="literal">ST_Intersects()</code></a></td>
<td>
      Whether one geometry intersects another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-isclosed"><code class="literal">ST_IsClosed()</code></a></td>
<td>
      Whether a geometry is closed and simple
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-isempty"><code class="literal">ST_IsEmpty()</code></a></td>
<td>
      Placeholder function
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-issimple"><code class="literal">ST_IsSimple()</code></a></td>
<td>
      Whether a geometry is simple
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-isvalid"><code class="literal">ST_IsValid()</code></a></td>
<td>
      Whether a geometry is valid
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-latfromgeohash"><code class="literal">ST_LatFromGeoHash()</code></a></td>
<td>
      Return latitude from geohash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-latitude"><code class="literal">ST_Latitude()</code></a> (introduced 8.0.12)</td>
<td>
      Return latitude of Point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-length"><code class="literal">ST_Length()</code></a></td>
<td>
      Return length of LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-linefromtext"><code class="literal">ST_LineFromText()</code>, <code class="literal">ST_LineStringFromText()</code></a></td>
<td>
      Construct LineString from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-linefromwkb"><code class="literal">ST_LineFromWKB()</code>, <code class="literal">ST_LineStringFromWKB()</code></a></td>
<td>
      Construct LineString from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-longfromgeohash"><code class="literal">ST_LongFromGeoHash()</code></a></td>
<td>
      Return longitude from geohash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-longitude"><code class="literal">ST_Longitude()</code></a> (introduced 8.0.12)</td>
<td>
      Return longitude of Point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-makeenvelope"><code class="literal">ST_MakeEnvelope()</code></a></td>
<td>
      Rectangle around two points
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mlinefromtext"><code class="literal">ST_MLineFromText()</code>, <code class="literal">ST_MultiLineStringFromText()</code></a></td>
<td>
      Construct MultiLineString from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mlinefromwkb"><code class="literal">ST_MLineFromWKB()</code>, <code class="literal">ST_MultiLineStringFromWKB()</code></a></td>
<td>
      Construct MultiLineString from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpointfromtext"><code class="literal">ST_MPointFromText()</code>, <code class="literal">ST_MultiPointFromText()</code></a></td>
<td>
      Construct MultiPoint from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpointfromwkb"><code class="literal">ST_MPointFromWKB()</code>, <code class="literal">ST_MultiPointFromWKB()</code></a></td>
<td>
      Construct MultiPoint from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpolyfromtext"><code class="literal">ST_MPolyFromText()</code>, <code class="literal">ST_MultiPolygonFromText()</code></a></td>
<td>
      Construct MultiPolygon from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpolyfromwkb"><code class="literal">ST_MPolyFromWKB()</code>, <code class="literal">ST_MultiPolygonFromWKB()</code></a></td>
<td>
      Construct MultiPolygon from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-numgeometries"><code class="literal">ST_NumGeometries()</code></a></td>
<td>
      Return number of geometries in geometry collection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-numinteriorrings"><code class="literal">ST_NumInteriorRing()</code>, <code class="literal">ST_NumInteriorRings()</code></a></td>
<td>
      Return number of interior rings in Polygon
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-numpoints"><code class="literal">ST_NumPoints()</code></a></td>
<td>
      Return number of points in LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-overlaps"><code class="literal">ST_Overlaps()</code></a></td>
<td>
      Whether one geometry overlaps another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointfromgeohash"><code class="literal">ST_PointFromGeoHash()</code></a></td>
<td>
      Convert geohash value to POINT value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointfromtext"><code class="literal">ST_PointFromText()</code></a></td>
<td>
      Construct Point from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointfromwkb"><code class="literal">ST_PointFromWKB()</code></a></td>
<td>
      Construct Point from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointn"><code class="literal">ST_PointN()</code></a></td>
<td>
      Return N-th point from LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-polyfromtext"><code class="literal">ST_PolyFromText()</code>, <code class="literal">ST_PolygonFromText()</code></a></td>
<td>
      Construct Polygon from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-polyfromwkb"><code class="literal">ST_PolyFromWKB()</code>, <code class="literal">ST_PolygonFromWKB()</code></a></td>
<td>
      Construct Polygon from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-simplify"><code class="literal">ST_Simplify()</code></a></td>
<td>
      Return simplified geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a></td>
<td>
      Return spatial reference system ID for geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-startpoint"><code class="literal">ST_StartPoint()</code></a></td>
<td>
      Start Point of LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-swapxy"><code class="literal">ST_SwapXY()</code></a></td>
<td>
      Return argument with X/Y coordinates swapped
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-symdifference"><code class="literal">ST_SymDifference()</code></a></td>
<td>
      Return point set symmetric difference of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-touches"><code class="literal">ST_Touches()</code></a></td>
<td>
      Whether one geometry touches another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform()</code></a> (introduced 8.0.13)</td>
<td>
      Transform coordinates of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-union"><code class="literal">ST_Union()</code></a></td>
<td>
      Return point set union of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate()</code></a></td>
<td>
      Return validated geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-within"><code class="literal">ST_Within()</code></a></td>
<td>
      Whether one geometry is within another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-x"><code class="literal">ST_X()</code></a></td>
<td>
      Return X coordinate of Point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-y"><code class="literal">ST_Y()</code></a></td>
<td>
      Return Y coordinate of Point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_statement-digest"><code class="literal">STATEMENT_DIGEST()</code></a></td>
<td>
      Compute statement digest hash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_statement-digest-text"><code class="literal">STATEMENT_DIGEST_TEXT()</code></a></td>
<td>
      Compute normalized statement digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_std"><code class="literal">STD()</code></a></td>
<td>
      Return the population standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_stddev"><code class="literal">STDDEV()</code></a></td>
<td>
      Return the population standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_stddev-pop"><code class="literal">STDDEV_POP()</code></a></td>
<td>
      Return the population standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_stddev-samp"><code class="literal">STDDEV_SAMP()</code></a></td>
<td>
      Return the sample standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE()</code></a></td>
<td>
      Convert a string to a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_strcmp"><code class="literal">STRCMP()</code></a></td>
<td>
      Compare two strings
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_subdate"><code class="literal">SUBDATE()</code></a></td>
<td>
      Synonym for DATE_SUB() when invoked with three arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR()</code></a></td>
<td>
      Return the substring as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING()</code></a></td>
<td>
      Return the substring as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_substring-index"><code class="literal">SUBSTRING_INDEX()</code></a></td>
<td>
      Return a substring from a string before the specified number of
      occurrences of the delimiter
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_subtime"><code class="literal">SUBTIME()</code></a></td>
<td>
      Subtract times
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a></td>
<td>
      Return the sum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a></td>
<td>
      Return the time at which the function executes
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_system-user"><code class="literal">SYSTEM_USER()</code></a></td>
<td>
      Synonym for USER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_tan"><code class="literal">TAN()</code></a></td>
<td>
      Return the tangent of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_time"><code class="literal">TIME()</code></a></td>
<td>
      Extract the time portion of the expression passed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_time-format"><code class="literal">TIME_FORMAT()</code></a></td>
<td>
      Format as time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_time-to-sec"><code class="literal">TIME_TO_SEC()</code></a></td>
<td>
      Return the argument converted to seconds
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timediff"><code class="literal">TIMEDIFF()</code></a></td>
<td>
      Subtract time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timestamp"><code class="literal">TIMESTAMP()</code></a></td>
<td>
      With a single argument, this function returns the date or datetime
      expression; with two arguments, the sum of the arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timestampadd"><code class="literal">TIMESTAMPADD()</code></a></td>
<td>
      Add an interval to a datetime expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timestampdiff"><code class="literal">TIMESTAMPDIFF()</code></a></td>
<td>
      Subtract an interval from a datetime expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_to-base64"><code class="literal">TO_BASE64()</code></a></td>
<td>
      Return the argument converted to a base-64 string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS()</code></a></td>
<td>
      Return the date argument converted to days
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_to-seconds"><code class="literal">TO_SECONDS()</code></a></td>
<td>
      Return the date or datetime argument converted to seconds since
      Year 0
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_trim"><code class="literal">TRIM()</code></a></td>
<td>
      Remove leading and trailing spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_truncate"><code class="literal">TRUNCATE()</code></a></td>
<td>
      Truncate to specified number of decimal places
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ucase"><code class="literal">UCASE()</code></a></td>
<td>
      Synonym for UPPER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uncompress"><code class="literal">UNCOMPRESS()</code></a></td>
<td>
      Uncompress a string compressed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uncompressed-length"><code class="literal">UNCOMPRESSED_LENGTH()</code></a></td>
<td>
      Return the length of a string before compression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a></td>
<td>
      Return a string containing hex representation of a number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a></td>
<td>
      Return a Unix timestamp
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_updatexml"><code class="literal">UpdateXML()</code></a></td>
<td>
      Return replaced XML fragment
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a></td>
<td>
      Convert to uppercase
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a></td>
<td>
      The user name and host name provided by the client
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_utc-date"><code class="literal">UTC_DATE()</code></a></td>
<td>
      Return the current UTC date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_utc-time"><code class="literal">UTC_TIME()</code></a></td>
<td>
      Return the current UTC time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_utc-timestamp"><code class="literal">UTC_TIMESTAMP()</code></a></td>
<td>
      Return the current UTC date and time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a></td>
<td>
      Return a Universal Unique Identifier (UUID)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a></td>
<td>
      Return an integer-valued universal identifier
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a></td>
<td>
      Convert string UUID to binary
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_validate-password-strength"><code class="literal">VALIDATE_PASSWORD_STRENGTH()</code></a></td>
<td>
      Determine strength of password
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_values"><code class="literal">VALUES()</code></a></td>
<td>
      Define the values to be used during an INSERT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_var-pop"><code class="literal">VAR_POP()</code></a></td>
<td>
      Return the population standard variance
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_var-samp"><code class="literal">VAR_SAMP()</code></a></td>
<td>
      Return the sample variance
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_variance"><code class="literal">VARIANCE()</code></a></td>
<td>
      Return the population standard variance
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_version"><code class="literal">VERSION()</code></a></td>
<td>
      Return a string that indicates the MySQL server version
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_wait-for-executed-gtid-set"><code class="literal">WAIT_FOR_EXECUTED_GTID_SET()</code></a></td>
<td>
      Wait until the given GTIDs have executed on the slave.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_wait-until-sql-thread-after-gtids"><code class="literal">WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()</code></a> (deprecated 8.0.18)</td>
<td>
      Use <code class="literal">WAIT_FOR_EXECUTED_GTID_SET()</code>.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a></td>
<td>
      Return the week number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_weekday"><code class="literal">WEEKDAY()</code></a></td>
<td>
      Return the weekday index
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_weekofyear"><code class="literal">WEEKOFYEAR()</code></a></td>
<td>
      Return the calendar week of the date (1-53)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING()</code></a></td>
<td>
      Return the weight string for a string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_xor"><code class="literal">XOR</code></a></td>
<td>
      Logical XOR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_year"><code class="literal">YEAR()</code></a></td>
<td>
      Return the year
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_yearweek"><code class="literal">YEARWEEK()</code></a></td>
<td>
      Return the year and week
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-or"><code class="literal">|</code></a></td>
<td>
      Bitwise OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a></td>
<td>
      Bitwise inversion
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="type-conversion"></a>12.2 Type Conversion in Expression Evaluation</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444332994928"></a><a class="indexterm" name="idm46444332993888"></a><p>
      When an operator is used with operands of different types, type
      conversion occurs to make the operands compatible. Some
      conversions occur implicitly. For example, MySQL automatically
      converts strings to numbers as necessary, and vice versa.
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1+'1';</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT CONCAT(2,' test');</code></strong>
        -&gt; '2 test'
</pre><p>
      It is also possible to convert a number to a string explicitly
      using the <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> function.
      Conversion occurs implicitly with the
      <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a> function because it
      expects string arguments.
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 38.8, CAST(38.8 AS CHAR);</code></strong>
        -&gt; 38.8, '38.8'
mysql&gt; <strong class="userinput"><code>SELECT 38.8, CONCAT(38.8);</code></strong>
        -&gt; 38.8, '38.8'
</pre><p>
      See later in this section for information about the character set
      of implicit number-to-string conversions, and for modified rules
      that apply to <code class="literal">CREATE TABLE ... SELECT</code>
      statements.
    </p><p>
      The following rules describe how conversion occurs for comparison
      operations:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If one or both arguments are <code class="literal">NULL</code>, the
          result of the comparison is <code class="literal">NULL</code>, except
          for the <code class="literal">NULL</code>-safe
          <a class="link" href="functions.html#operator_equal-to"><code class="literal">&lt;=&gt;</code></a>
          equality comparison operator. For <code class="literal">NULL &lt;=&gt;
          NULL</code>, the result is true. No conversion is needed.
        </p></li><li class="listitem"><p>
          If both arguments in a comparison operation are strings, they
          are compared as strings.
        </p></li><li class="listitem"><p>
          If both arguments are integers, they are compared as integers.
        </p></li><li class="listitem"><p>
          Hexadecimal values are treated as binary strings if not
          compared to a number.
        </p></li><li class="listitem"><p>
          If one of the arguments is a
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> or
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> column and the other
          argument is a constant, the constant is converted to a
          timestamp before the comparison is performed. This is done to
          be more ODBC-friendly. This is not done for the arguments to
          <a class="link" href="functions.html#operator_in"><code class="literal">IN()</code></a>. To be safe, always use
          complete datetime, date, or time strings when doing
          comparisons. For example, to achieve best results when using
          <a class="link" href="functions.html#operator_between"><code class="literal">BETWEEN</code></a> with date or time values,
          use <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> to explicitly
          convert the values to the desired data type.
        </p><p>
          A single-row subquery from a table or tables is not considered
          a constant. For example, if a subquery returns an integer to
          be compared to a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>
          value, the comparison is done as two integers. The integer is
          not converted to a temporal value. To compare the operands as
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> values, use
          <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> to explicitly convert
          the subquery value to <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>.
        </p><a class="indexterm" name="idm46444332961376"></a><a class="indexterm" name="idm46444332960304"></a></li><li class="listitem"><p>
          If one of the arguments is a decimal value, comparison depends
          on the other argument. The arguments are compared as decimal
          values if the other argument is a decimal or integer value, or
          as floating-point values if the other argument is a
          floating-point value.
        </p></li><li class="listitem"><p>
          In all other cases, the arguments are compared as
          floating-point (real) numbers. For example, a comparison of
          string and numeric operands takes places as a comparison of
          floating-point numbers.
</p></li></ul>
</div>
<p>
      For information about conversion of values from one temporal type
      to another, see <a class="xref" href="data-types.html#date-and-time-type-conversion" title="11.2.7 Conversion Between Date and Time Types">Section 11.2.7, “Conversion Between Date and Time Types”</a>.
    </p><p>
      Comparison of JSON values takes place at two levels. The first
      level of comparison is based on the JSON types of the compared
      values. If the types differ, the comparison result is determined
      solely by which type has higher precedence. If the two values have
      the same JSON type, a second level of comparison occurs using
      type-specific rules. For comparison of JSON and non-JSON values,
      the non-JSON value is converted to JSON and the values compared as
      JSON values. For details, see <a class="xref" href="data-types.html#json-comparison" title="Comparison and Ordering of JSON Values">Comparison and Ordering of JSON Values</a>.
    </p><p>
      The following examples illustrate conversion of strings to numbers
      for comparison operations:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 &gt; '6x';</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 7 &gt; '6x';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 0 &gt; 'x6';</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 0 = 'x6';</code></strong>
        -&gt; 1
</pre><p>
      For comparisons of a string column with a number, MySQL cannot use
      an index on the column to look up the value quickly. If
      <em class="replaceable"><code>str_col</code></em> is an indexed string column,
      the index cannot be used when performing the lookup in the
      following statement:
    </p><pre data-lang="sql" class="programlisting">SELECT * FROM <em class="replaceable"><code>tbl_name</code></em> WHERE <em class="replaceable"><code>str_col</code></em>=1;
</pre><p>
      The reason for this is that there are many different strings that
      may convert to the value <code class="literal">1</code>, such as
      <code class="literal">'1'</code>, <code class="literal">' 1'</code>, or
      <code class="literal">'1a'</code>.
    </p><p>
      Comparisons between floating-point numbers and large values of
      <code class="literal">INTEGER</code> type are approximate because the
      integer is converted to double-precision floating point before
      comparison, which is not capable of representing all 64-bit
      integers exactly. For example, the integer value
      2<sup>53</sup> + 1 is not representable as a
      float, and will be rounded to 2<sup>53</sup> or
      2<sup>53</sup> + 2 before a float comparison,
      depending on the platform.
    </p><p>
      To illustrate, only the first of the following comparisons
      compares equal values, but both comparisons return true (1):
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT '9223372036854775807' = 9223372036854775807;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT '9223372036854775807' = 9223372036854775806;</code></strong>
        -&gt; 1
</pre><p>
      When conversions from string to floating-point and from integer to
      floating-point occur, they do not necessarily occur the same way.
      The integer may be converted to floating-point by the CPU, whereas
      the string is converted digit by digit in an operation that
      involves floating-point multiplications. Also, results can be
      affected by factors such as computer architecture or the compiler
      version or optimization level. One way to avoid such problems is
      to use <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> so that a value is
      not converted implicitly to a float-point number:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CAST('9223372036854775807' AS UNSIGNED) = 9223372036854775806;</code></strong>
        -&gt; 0
</pre><p>
      For more information about floating-point comparisons, see
      <a class="xref" href="error-handling.html#problems-with-float" title="B.4.4.8 Problems with Floating-Point Values">Section B.4.4.8, “Problems with Floating-Point Values”</a>.
    </p><p>
      The server includes <code class="literal">dtoa</code>, a conversion library
      that provides the basis for improved conversion between string or
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> values and
      approximate-value
      (<a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a>/<a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a>)
      numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Consistent conversion results across platforms, which
          eliminates, for example, Unix versus Windows conversion
          differences.
        </p></li><li class="listitem"><p>
          Accurate representation of values in cases where results
          previously did not provide sufficient precision, such as for
          values close to IEEE limits.
        </p></li><li class="listitem"><p>
          Conversion of numbers to string format with the best possible
          precision. The precision of <code class="literal">dtoa</code> is always
          the same or better than that of the standard C library
          functions.
</p></li></ul>
</div>
<p>
      Because the conversions produced by this library differ in some
      cases from non-<code class="literal">dtoa</code> results, the potential
      exists for incompatibilities in applications that rely on previous
      results. For example, applications that depend on a specific exact
      result from previous conversions might need adjustment to
      accommodate additional precision.
    </p><p>
      The <code class="literal">dtoa</code> library provides conversions with the
      following properties. <em class="replaceable"><code>D</code></em> represents a
      value with a <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> or string
      representation, and <em class="replaceable"><code>F</code></em> represents a
      floating-point number in native binary (IEEE) format.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          <em class="replaceable"><code>F</code></em> -&gt;
          <em class="replaceable"><code>D</code></em> conversion is done with the best
          possible precision, returning <em class="replaceable"><code>D</code></em> as
          the shortest string that yields <em class="replaceable"><code>F</code></em>
          when read back in and rounded to the nearest value in native
          binary format as specified by IEEE.
        </p></li><li class="listitem"><p>
          <em class="replaceable"><code>D</code></em> -&gt;
          <em class="replaceable"><code>F</code></em> conversion is done such that
          <em class="replaceable"><code>F</code></em> is the nearest native binary
          number to the input decimal string
          <em class="replaceable"><code>D</code></em>.
</p></li></ul>
</div>
<p>
      These properties imply that <em class="replaceable"><code>F</code></em> -&gt;
      <em class="replaceable"><code>D</code></em> -&gt; <em class="replaceable"><code>F</code></em>
      conversions are lossless unless <em class="replaceable"><code>F</code></em> is
      <code class="literal">-inf</code>, <code class="literal">+inf</code>, or
      <code class="literal">NaN</code>. The latter values are not supported
      because the SQL standard defines them as invalid values for
      <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a> or
      <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a>.
    </p><p>
      For <em class="replaceable"><code>D</code></em> -&gt;
      <em class="replaceable"><code>F</code></em> -&gt; <em class="replaceable"><code>D</code></em>
      conversions, a sufficient condition for losslessness is that
      <em class="replaceable"><code>D</code></em> uses 15 or fewer digits of precision,
      is not a denormal value, <code class="literal">-inf</code>,
      <code class="literal">+inf</code>, or <code class="literal">NaN</code>. In some cases,
      the conversion is lossless even if <em class="replaceable"><code>D</code></em>
      has more than 15 digits of precision, but this is not always the
      case.
    </p><p>
      Implicit conversion of a numeric or temporal value to string
      produces a value that has a character set and collation determined
      by the <a class="link" href="server-administration.html#sysvar_character_set_connection"><code class="literal">character_set_connection</code></a>
      and <a class="link" href="server-administration.html#sysvar_collation_connection"><code class="literal">collation_connection</code></a> system
      variables. (These variables commonly are set with
      <a class="link" href="sql-statements.html#set-names" title="13.7.6.3 SET NAMES Statement"><code class="literal">SET NAMES</code></a>. For information about
      connection character sets, see
      <a class="xref" href="charset.html#charset-connection" title="10.4 Connection Character Sets and Collations">Section 10.4, “Connection Character Sets and Collations”</a>.)
    </p><p>
      This means that such a conversion results in a character
      (nonbinary) string (a <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a>,
      <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>, or
      <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">LONGTEXT</code></a> value), except in the case
      that the connection character set is set to
      <code class="literal">binary</code>. In that case, the conversion result is
      a binary string (a <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
      <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>, or
      <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">LONGBLOB</code></a> value).
    </p><p>
      For integer expressions, the preceding remarks about expression
      <span class="emphasis"><em>evaluation</em></span> apply somewhat differently for
      expression <span class="emphasis"><em>assignment</em></span>; for example, in a
      statement such as this:
    </p><pre data-lang="sql" class="programlisting">CREATE TABLE t SELECT <em class="replaceable"><code>integer_expr</code></em>;
</pre><p>
      In this case, the table in the column resulting from the
      expression has type <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a> or
      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> depending on the length of
      the integer expression. If the maximum length of the expression
      does not fit in an <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a>,
      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> is used instead. The length
      is taken from the <code class="literal">max_length</code> value of the
      <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> result set metadata (see
      <a class="xref" href="connectors-apis.html#c-api-data-structures" title="28.7.4 C API Data Structures">Section 28.7.4, “C API Data Structures”</a>). This means that you can
      force a <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> rather than
      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a> by use of a sufficiently long
      expression:
</p><pre data-lang="sql" class="programlisting">CREATE TABLE t SELECT 000000000000000000000;</pre>
</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="non-typed-operators"></a>12.3 Operators</h2>

</div>

</div>

</div>

<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#operator-precedence">12.3.1 Operator Precedence</a></span></dt><dt><span class="section"><a href="functions.html#comparison-operators">12.3.2 Comparison Functions and Operators</a></span></dt><dt><span class="section"><a href="functions.html#logical-operators">12.3.3 Logical Operators</a></span></dt><dt><span class="section"><a href="functions.html#assignment-operators">12.3.4 Assignment Operators</a></span></dt></dl>
</div>

<div class="table">
<a name="idm46444332871488"></a><p class="title"><b>Table 12.2 Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists all operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a></td>
<td>
      Bitwise AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_greater-than"><code class="literal">&gt;</code></a></td>
<td>
      Greater than operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_right-shift"><code class="literal">&gt;&gt;</code></a></td>
<td>
      Right shift
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_greater-than-or-equal"><code class="literal">&gt;=</code></a></td>
<td>
      Greater than or equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_less-than"><code class="literal">&lt;</code></a></td>
<td>
      Less than operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-equal"><code class="literal">&lt;&gt;</code>, <code class="literal">!=</code></a></td>
<td>
      Not equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_left-shift"><code class="literal">&lt;&lt;</code></a></td>
<td>
      Left shift
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_less-than-or-equal"><code class="literal">&lt;=</code></a></td>
<td>
      Less than or equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_equal-to"><code class="literal">&lt;=&gt;</code></a></td>
<td>
      NULL-safe equal to operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_mod"><code class="literal">%</code>, <code class="literal">MOD</code></a></td>
<td>
      Modulo operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_times"><code class="literal">*</code></a></td>
<td>
      Multiplication operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a></td>
<td>
      Addition operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a></td>
<td>
      Minus operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_unary-minus"><code class="literal">-</code></a></td>
<td>
      Change the sign of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a></td>
<td>
      Return value from JSON column after evaluating path; equivalent to
      JSON_EXTRACT().
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_json-inline-path"><code class="literal">-&gt;&gt;</code></a></td>
<td>
      Return value from JSON column after evaluating path and unquoting
      the result; equivalent to JSON_UNQUOTE(JSON_EXTRACT()).
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_divide"><code class="literal">/</code></a></td>
<td>
      Division operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a></td>
<td>
      Assign a value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_assign-equal"><code class="literal">=</code></a></td>
<td>
      Assign a value (as part of a
      <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
      statement, or as part of the <code class="literal">SET</code> clause in an
      <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a></td>
<td>
      Equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-xor"><code class="literal">^</code></a></td>
<td>
      Bitwise XOR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_and"><code class="literal">AND</code>, <code class="literal">&amp;&amp;</code></a></td>
<td>
      Logical AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_between"><code class="literal">BETWEEN ... AND ...</code></a></td>
<td>
      Whether a value is within a range of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a></td>
<td>
      Cast a string to a binary string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_case"><code class="literal">CASE</code></a></td>
<td>
      Case operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_div"><code class="literal">DIV</code></a></td>
<td>
      Integer division
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_in"><code class="literal">IN()</code></a></td>
<td>
      Whether a value is within a set of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is"><code class="literal">IS</code></a></td>
<td>
      Test a value against a boolean
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-not"><code class="literal">IS NOT</code></a></td>
<td>
      Test a value against a boolean
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-not-null"><code class="literal">IS NOT NULL</code></a></td>
<td>
      NOT NULL value test
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-null"><code class="literal">IS NULL</code></a></td>
<td>
      NULL value test
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a></td>
<td>
      Simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_member-of"><code class="literal">MEMBER OF()</code></a> (introduced 8.0.17)</td>
<td>
      Returns true (1) if first operand matches any element of JSON
      array passed as second operand, otherwise returns false (0)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not"><code class="literal">NOT</code>, <code class="literal">!</code></a></td>
<td>
      Negates value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-between"><code class="literal">NOT BETWEEN ... AND ...</code></a></td>
<td>
      Whether a value is not within a range of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-in"><code class="literal">NOT IN()</code></a></td>
<td>
      Whether a value is not within a set of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-like"><code class="literal">NOT LIKE</code></a></td>
<td>
      Negation of simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-regexp"><code class="literal">NOT REGEXP</code></a></td>
<td>
      Negation of REGEXP
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_or"><code class="literal">OR</code>, <code class="literal">||</code></a></td>
<td>
      Logical OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">REGEXP</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">RLIKE</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_sounds-like"><code class="literal">SOUNDS LIKE</code></a></td>
<td>
      Compare sounds
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_xor"><code class="literal">XOR</code></a></td>
<td>
      Logical XOR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-or"><code class="literal">|</code></a></td>
<td>
      Bitwise OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a></td>
<td>
      Bitwise inversion
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="operator-precedence"></a>12.3.1 Operator Precedence</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444332712768"></a><a class="indexterm" name="idm46444332711280"></a><p>
        Operator precedences are shown in the following list, from
        highest precedence to the lowest. Operators that are shown
        together on a line have the same precedence.
      </p><pre data-lang="sql" class="programlisting">INTERVAL
BINARY, COLLATE
!
- (unary minus), ~ (unary bit inversion)
^
*, /, DIV, %, MOD
-, +
&lt;&lt;, &gt;&gt;
&amp;
|
= (comparison), &lt;=&gt;, &gt;=, &gt;, &lt;=, &lt;, &lt;&gt;, !=, IS, LIKE, REGEXP, IN, MEMBER OF
BETWEEN, CASE, WHEN, THEN, ELSE
NOT
AND, &amp;&amp;
XOR
OR, ||
= (assignment), :=</pre><p>
        The precedence of <code class="literal">=</code> depends on whether it is
        used as a comparison operator
        (<a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a>) or as an
        assignment operator
        (<a class="link" href="functions.html#operator_assign-equal"><code class="literal">=</code></a>). When
        used as a comparison operator, it has the same precedence as
        <a class="link" href="functions.html#operator_equal-to"><code class="literal">&lt;=&gt;</code></a>,
        <a class="link" href="functions.html#operator_greater-than-or-equal"><code class="literal">&gt;=</code></a>,
        <a class="link" href="functions.html#operator_greater-than"><code class="literal">&gt;</code></a>,
        <a class="link" href="functions.html#operator_less-than-or-equal"><code class="literal">&lt;=</code></a>,
        <a class="link" href="functions.html#operator_less-than"><code class="literal">&lt;</code></a>,
        <a class="link" href="functions.html#operator_not-equal"><code class="literal">&lt;&gt;</code></a>,
        <a class="link" href="functions.html#operator_not-equal"><code class="literal">!=</code></a>,
        <a class="link" href="functions.html#operator_is"><code class="literal">IS</code></a>,
        <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a>,
        <a class="link" href="functions.html#operator_regexp"><code class="literal">REGEXP</code></a>, and
        <a class="link" href="functions.html#operator_in"><code class="literal">IN()</code></a>. When used as an assignment
        operator, it has the same precedence as
        <a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a>.
        <a class="xref" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment">Section 13.7.6.1, “SET Syntax for Variable Assignment”</a>, and
        <a class="xref" href="language-structure.html#user-variables" title="9.4 User-Defined Variables">Section 9.4, “User-Defined Variables”</a>, explain how MySQL determines
        which interpretation of <code class="literal">=</code> should apply.
      </p><p>
        For operators that occur at the same precedence level within an
        expression, evaluation proceeds left to right, with the
        exception that assignments evaluate right to left.
      </p><p>
        The precedence and meaning of some operators depends on the SQL
        mode:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            By default, <a class="link" href="functions.html#operator_or"><code class="literal">||</code></a>
            is a logical <a class="link" href="functions.html#operator_or"><code class="literal">OR</code></a> operator. With
            <a class="link" href="server-administration.html#sqlmode_pipes_as_concat"><code class="literal">PIPES_AS_CONCAT</code></a> enabled,
            <a class="link" href="functions.html#operator_or"><code class="literal">||</code></a> is string
            concatenation, with a precedence between
            <a class="link" href="functions.html#operator_bitwise-xor"><code class="literal">^</code></a> and
            the unary operators.
          </p></li><li class="listitem"><p>
            By default, <a class="link" href="functions.html#operator_not"><code class="literal">!</code></a>
            has a higher precedence than <code class="literal">NOT</code>. With
            <a class="link" href="server-administration.html#sqlmode_high_not_precedence"><code class="literal">HIGH_NOT_PRECEDENCE</code></a>
            enabled, <a class="link" href="functions.html#operator_not"><code class="literal">!</code></a> and
            <code class="literal">NOT</code> have the same precedence.
</p></li></ul>
</div>
<p>
        See <a class="xref" href="server-administration.html#sql-mode" title="5.1.11 Server SQL Modes">Section 5.1.11, “Server SQL Modes”</a>.
      </p><a class="indexterm" name="idm46444332670880"></a><a class="indexterm" name="idm46444332669808"></a><a class="indexterm" name="idm46444332668736"></a><a class="indexterm" name="idm46444332667248"></a><p>
        The precedence of operators determines the order of evaluation
        of terms in an expression. To override this order and group
        terms explicitly, use parentheses. For example:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1+2*3;</code></strong>
        -&gt; 7
mysql&gt; <strong class="userinput"><code>SELECT (1+2)*3;</code></strong>
        -&gt; 9
</pre>
</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="comparison-operators"></a>12.3.2 Comparison Functions and Operators</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444332661504"></a>
<div class="table">
<a name="idm46444332660464"></a><p class="title"><b>Table 12.3 Comparison Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists comparison operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_greater-than"><code class="literal">&gt;</code></a></td>
<td>
      Greater than operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_greater-than-or-equal"><code class="literal">&gt;=</code></a></td>
<td>
      Greater than or equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_less-than"><code class="literal">&lt;</code></a></td>
<td>
      Less than operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-equal"><code class="literal">&lt;&gt;</code>, <code class="literal">!=</code></a></td>
<td>
      Not equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_less-than-or-equal"><code class="literal">&lt;=</code></a></td>
<td>
      Less than or equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_equal-to"><code class="literal">&lt;=&gt;</code></a></td>
<td>
      NULL-safe equal to operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a></td>
<td>
      Equal operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_between"><code class="literal">BETWEEN ... AND ...</code></a></td>
<td>
      Whether a value is within a range of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_coalesce"><code class="literal">COALESCE()</code></a></td>
<td>
      Return the first non-NULL argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_greatest"><code class="literal">GREATEST()</code></a></td>
<td>
      Return the largest argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_in"><code class="literal">IN()</code></a></td>
<td>
      Whether a value is within a set of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_interval"><code class="literal">INTERVAL()</code></a></td>
<td>
      Return the index of the argument that is less than the first
      argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is"><code class="literal">IS</code></a></td>
<td>
      Test a value against a boolean
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-not"><code class="literal">IS NOT</code></a></td>
<td>
      Test a value against a boolean
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-not-null"><code class="literal">IS NOT NULL</code></a></td>
<td>
      NOT NULL value test
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_is-null"><code class="literal">IS NULL</code></a></td>
<td>
      NULL value test
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_isnull"><code class="literal">ISNULL()</code></a></td>
<td>
      Test whether the argument is NULL
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_least"><code class="literal">LEAST()</code></a></td>
<td>
      Return the smallest argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a></td>
<td>
      Simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-between"><code class="literal">NOT BETWEEN ... AND ...</code></a></td>
<td>
      Whether a value is not within a range of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-in"><code class="literal">NOT IN()</code></a></td>
<td>
      Whether a value is not within a set of values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-like"><code class="literal">NOT LIKE</code></a></td>
<td>
      Negation of simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_strcmp"><code class="literal">STRCMP()</code></a></td>
<td>
      Compare two strings
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><a class="indexterm" name="idm46444332578416"></a><a class="indexterm" name="idm46444332577344"></a><p>
        Comparison operations result in a value of <code class="literal">1</code>
        (<code class="literal">TRUE</code>), <code class="literal">0</code>
        (<code class="literal">FALSE</code>), or <code class="literal">NULL</code>. These
        operations work for both numbers and strings. Strings are
        automatically converted to numbers and numbers to strings as
        necessary.
      </p><p>
        The following relational comparison operators can be used to
        compare not only scalar operands, but row operands:
      </p><pre data-lang="sql" class="programlisting">=  &gt;  &lt;  &gt;=  &lt;=  &lt;&gt;  !=</pre><p>
        The descriptions for those operators later in this section
        detail how they work with row operands. For additional examples
        of row comparisons in the context of row subqueries, see
        <a class="xref" href="sql-statements.html#row-subqueries" title="13.2.11.5 Row Subqueries">Section 13.2.11.5, “Row Subqueries”</a>.
      </p><p>
        Some of the functions in this section return values other than
        <code class="literal">1</code> (<code class="literal">TRUE</code>),
        <code class="literal">0</code> (<code class="literal">FALSE</code>), or
        <code class="literal">NULL</code>. <a class="link" href="functions.html#function_least"><code class="literal">LEAST()</code></a>
        and <a class="link" href="functions.html#function_greatest"><code class="literal">GREATEST()</code></a> are examples of
        such functions; <a class="xref" href="functions.html#type-conversion" title="12.2 Type Conversion in Expression Evaluation">Section 12.2, “Type Conversion in Expression Evaluation”</a>, describes the
        rules for comparison operations performed by these and similar
        functions for determining their return values.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          In previous versions of MySQL, when evaluating an expression
          containing <code class="literal">LEAST()</code> or
          <code class="literal">GREATEST()</code>, the server attempted to guess
          the context in which the function was used, and to coerce the
          function's arguments to the data type of the expression
          as a whole. For example, the arguments to <code class="literal">LEAST("11",
          "45", "2")</code> are evaluated and sorted as strings, so
          that this expression returns <code class="literal">"11"</code>. In MySQL
          8.0.3 and earlier, when evaluating the expression
          <code class="literal">LEAST("11", "45", "2") + 0</code>, the server
          converted the arguments to integers (anticipating the addition
          of integer 0 to the result) before sorting them, thus
          returning 2.
        </p><p>
          Beginning with MySQL 8.0.4, the server no longer attempts to
          infer context in this fashion. Instead, the function is
          executed using the arguments as provided, performing data type
          conversions to one or more of the arguments if and only if
          they are not all of the same type. Any type coercion mandated
          by an expression that makes use of the return value is now
          performed following function execution. This means that, in
          MySQl 8.0.4 and later, <code class="literal">LEAST("11", "45", "2") +
          0</code> evaluates to <code class="literal">"11" + 0</code> and thus
          to integer 11. (Bug #83895, Bug #25123839)
</p>
</div>
<p>
        To convert a value to a specific type for comparison purposes,
        you can use the <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> function.
        String values can be converted to a different character set
        using <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a>. See
        <a class="xref" href="functions.html#cast-functions" title="12.10 Cast Functions and Operators">Section 12.10, “Cast Functions and Operators”</a>.
      </p><p>
        By default, string comparisons are not case-sensitive and use
        the current character set. The default is
        <code class="literal">utf8mb4</code>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_equal"></a><p>
            <a class="indexterm" name="idm46444332547136"></a>

            <a class="indexterm" name="idm46444332546064"></a>

            <a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a>
          </p><p>
            Equal:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 = 0;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT '0' = 0;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT '0.0' = 0;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT '0.01' = 0;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT '.01' = 0.01;</code></strong>
        -&gt; 1
</pre><p>
            For row comparisons, <code class="literal">(a, b) = (x, y)</code> is
            equivalent to:
          </p><pre data-lang="sql" class="programlisting">(a = x) AND (b = y)</pre></li><li class="listitem"><a name="operator_equal-to"></a><p>
            <a class="indexterm" name="idm46444332533168"></a>

            <a class="indexterm" name="idm46444332531680"></a>

            <a class="link" href="functions.html#operator_equal-to"><code class="literal">&lt;=&gt;</code></a>
          </p><p>
            <code class="literal">NULL</code>-safe equal. This operator performs
            an equality comparison like the
            <a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a> operator,
            but returns <code class="literal">1</code> rather than
            <code class="literal">NULL</code> if both operands are
            <code class="literal">NULL</code>, and <code class="literal">0</code> rather
            than <code class="literal">NULL</code> if one operand is
            <code class="literal">NULL</code>.
          </p><a class="indexterm" name="idm46444332521488"></a><p>
            The
            <a class="link" href="functions.html#operator_equal-to"><code class="literal">&lt;=&gt;</code></a>
            operator is equivalent to the standard SQL <code class="literal">IS NOT
            DISTINCT FROM</code> operator.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 &lt;=&gt; 1, NULL &lt;=&gt; NULL, 1 &lt;=&gt; NULL;</code></strong>
        -&gt; 1, 1, 0
mysql&gt; <strong class="userinput"><code>SELECT 1 = 1, NULL = NULL, 1 = NULL;</code></strong>
        -&gt; 1, NULL, NULL
</pre><p>
            For row comparisons, <code class="literal">(a, b) &lt;=&gt; (x,
            y)</code> is equivalent to:
          </p><pre data-lang="sql" class="programlisting">(a &lt;=&gt; x) AND (b &lt;=&gt; y)</pre></li><li class="listitem"><a name="operator_not-equal"></a><p>
            <a class="indexterm" name="idm46444332509088"></a>

            <a class="indexterm" name="idm46444332508000"></a>

            <a class="indexterm" name="idm46444332506912"></a>

            <a class="indexterm" name="idm46444332505840"></a>

            <a class="link" href="functions.html#operator_not-equal"><code class="literal">&lt;&gt;</code></a>,
            <a class="link" href="functions.html#operator_not-equal"><code class="literal">!=</code></a>
          </p><p>
            Not equal:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT '.01' &lt;&gt; '0.01';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT .01 &lt;&gt; '0.01';</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 'zapp' &lt;&gt; 'zappp';</code></strong>
        -&gt; 1
</pre><p>
            For row comparisons, <code class="literal">(a, b) &lt;&gt; (x,
            y)</code> and <code class="literal">(a, b) != (x, y)</code> are
            equivalent to:
          </p><pre data-lang="sql" class="programlisting">(a &lt;&gt; x) OR (b &lt;&gt; y)</pre></li><li class="listitem"><a name="operator_less-than-or-equal"></a><p>
            <a class="indexterm" name="idm46444332491232"></a>

            <a class="indexterm" name="idm46444332490128"></a>

            <a class="link" href="functions.html#operator_less-than-or-equal"><code class="literal">&lt;=</code></a>
          </p><p>
            Less than or equal:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 0.1 &lt;= 2;</code></strong>
        -&gt; 1
</pre><p>
            For row comparisons, <code class="literal">(a, b) &lt;= (x, y)</code>
            is equivalent to:
          </p><pre data-lang="sql" class="programlisting">(a &lt; x) OR ((a = x) AND (b &lt;= y))</pre></li><li class="listitem"><a name="operator_less-than"></a><p>
            <a class="indexterm" name="idm46444332478928"></a>

            <a class="indexterm" name="idm46444332477840"></a>

            <a class="link" href="functions.html#operator_less-than"><code class="literal">&lt;</code></a>
          </p><p>
            Less than:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 2 &lt; 2;</code></strong>
        -&gt; 0
</pre><p>
            For row comparisons, <code class="literal">(a, b) &lt; (x, y)</code>
            is equivalent to:
          </p><pre data-lang="sql" class="programlisting">(a &lt; x) OR ((a = x) AND (b &lt; y))</pre></li><li class="listitem"><a name="operator_greater-than-or-equal"></a><p>
            <a class="indexterm" name="idm46444332466592"></a>

            <a class="indexterm" name="idm46444332465488"></a>

            <a class="link" href="functions.html#operator_greater-than-or-equal"><code class="literal">&gt;=</code></a>
          </p><p>
            Greater than or equal:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 2 &gt;= 2;</code></strong>
        -&gt; 1
</pre><p>
            For row comparisons, <code class="literal">(a, b) &gt;= (x, y)</code>
            is equivalent to:
          </p><pre data-lang="sql" class="programlisting">(a &gt; x) OR ((a = x) AND (b &gt;= y))</pre></li><li class="listitem"><a name="operator_greater-than"></a><p>
            <a class="indexterm" name="idm46444332454304"></a>

            <a class="indexterm" name="idm46444332453216"></a>

            <a class="link" href="functions.html#operator_greater-than"><code class="literal">&gt;</code></a>
          </p><p>
            Greater than:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 2 &gt; 2;</code></strong>
        -&gt; 0
</pre><p>
            For row comparisons, <code class="literal">(a, b) &gt; (x, y)</code>
            is equivalent to:
          </p><pre data-lang="sql" class="programlisting">(a &gt; x) OR ((a = x) AND (b &gt; y))</pre></li><li class="listitem"><a name="operator_between"></a><p>
            <a class="indexterm" name="idm46444332441344"></a>

            <a class="link" href="functions.html#operator_between"><code class="literal"><em class="replaceable"><code>expr</code></em>
            BETWEEN <em class="replaceable"><code>min</code></em> AND
            <em class="replaceable"><code>max</code></em></code></a>
          </p><p>
            If <em class="replaceable"><code>expr</code></em> is greater than or equal
            to <em class="replaceable"><code>min</code></em> and
            <em class="replaceable"><code>expr</code></em> is less than or equal to
            <em class="replaceable"><code>max</code></em>,
            <a class="link" href="functions.html#operator_between"><code class="literal">BETWEEN</code></a> returns
            <code class="literal">1</code>, otherwise it returns
            <code class="literal">0</code>. This is equivalent to the expression
            <code class="literal">(<em class="replaceable"><code>min</code></em> &lt;=
            <em class="replaceable"><code>expr</code></em> AND
            <em class="replaceable"><code>expr</code></em> &lt;=
            <em class="replaceable"><code>max</code></em>)</code> if all the
            arguments are of the same type. Otherwise type conversion
            takes place according to the rules described in
            <a class="xref" href="functions.html#type-conversion" title="12.2 Type Conversion in Expression Evaluation">Section 12.2, “Type Conversion in Expression Evaluation”</a>, but applied to all the
            three arguments.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;</code></strong>
        -&gt; 1, 0
mysql&gt; <strong class="userinput"><code>SELECT 1 BETWEEN 2 AND 3;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 'b' BETWEEN 'a' AND 'c';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 2 BETWEEN 2 AND '3';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 2 BETWEEN 2 AND 'x-3';</code></strong>
        -&gt; 0
</pre><p>
            For best results when using
            <a class="link" href="functions.html#operator_between"><code class="literal">BETWEEN</code></a> with date or time
            values, use <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> to
            explicitly convert the values to the desired data type.
            Examples: If you compare a
            <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> to two
            <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> values, convert the
            <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> values to
            <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> values. If you use a
            string constant such as <code class="literal">'2001-1-1'</code> in a
            comparison to a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a>, cast
            the string to a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a>.
          </p></li><li class="listitem"><a name="operator_not-between"></a><p>
            <a class="indexterm" name="idm46444332409328"></a>

            <a class="link" href="functions.html#operator_not-between"><code class="literal"><em class="replaceable"><code>expr</code></em>
            NOT BETWEEN <em class="replaceable"><code>min</code></em> AND
            <em class="replaceable"><code>max</code></em></code></a>
          </p><p>
            This is the same as <code class="literal">NOT
            (<em class="replaceable"><code>expr</code></em> BETWEEN
            <em class="replaceable"><code>min</code></em> AND
            <em class="replaceable"><code>max</code></em>)</code>.
          </p></li><li class="listitem"><a name="function_coalesce"></a><p>
            <a class="indexterm" name="idm46444332399632"></a>

            <a class="indexterm" name="idm46444332398144"></a>

            <a class="link" href="functions.html#function_coalesce"><code class="literal">COALESCE(<em class="replaceable"><code>value</code></em>,...)</code></a>
          </p><p>
            Returns the first non-<code class="literal">NULL</code> value in the
            list, or <code class="literal">NULL</code> if there are no
            non-<code class="literal">NULL</code> values.
          </p><p>
            The return type of <a class="link" href="functions.html#function_coalesce"><code class="literal">COALESCE()</code></a>
            is the aggregated type of the argument types.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COALESCE(NULL,1);</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT COALESCE(NULL,NULL,NULL);</code></strong>
        -&gt; NULL
</pre></li><li class="listitem"><a name="function_greatest"></a><p>
            <a class="indexterm" name="idm46444332384112"></a>

            <a class="link" href="functions.html#function_greatest"><code class="literal">GREATEST(<em class="replaceable"><code>value1</code></em>,<em class="replaceable"><code>value2</code></em>,...)</code></a>
          </p><p>
            With two or more arguments, returns the largest
            (maximum-valued) argument. The arguments are compared using
            the same rules as for
            <a class="link" href="functions.html#function_least"><code class="literal">LEAST()</code></a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT GREATEST(2,0);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT GREATEST(34.0,3.0,5.0,767.0);</code></strong>
        -&gt; 767.0
mysql&gt; <strong class="userinput"><code>SELECT GREATEST('B','A','C');</code></strong>
        -&gt; 'C'
</pre><p>
            <a class="link" href="functions.html#function_greatest"><code class="literal">GREATEST()</code></a> returns
            <code class="literal">NULL</code> if any argument is
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><a name="operator_in"></a><p>
            <a class="indexterm" name="idm46444332368400"></a>

            <a class="link" href="functions.html#operator_in"><code class="literal"><em class="replaceable"><code>expr</code></em>
            IN (<em class="replaceable"><code>value</code></em>,...)</code></a>
          </p><p>
            Returns <code class="literal">1</code> (true) if
            <em class="replaceable"><code>expr</code></em> is equal to any of the
            values in the <code class="literal">IN()</code> list, else returns
            <code class="literal">0</code> (false).
          </p><p>
            Type conversion takes place according to the rules described
            in <a class="xref" href="functions.html#type-conversion" title="12.2 Type Conversion in Expression Evaluation">Section 12.2, “Type Conversion in Expression Evaluation”</a>, applied to all the
            arguments. If no type conversion is needed for the values in
            the <code class="literal">IN()</code> list, they are all
            non-<code class="literal">JSON</code> constants of the same type, and
            <em class="replaceable"><code>expr</code></em> can be compared to each of
            them as a value of the same type (possibly after type
            conversion), an optimization takes place. The values the
            list are sorted and the search for
            <em class="replaceable"><code>expr</code></em> is done using a binary
            search, which makes the <code class="literal">IN()</code> operation
            very quick.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 2 IN (0,3,5,7);</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 'wefwf' IN ('wee','wefwf','weg');</code></strong>
        -&gt; 1
</pre><p>
            <code class="literal">IN()</code> can be used to compare row
            constructors:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT (3,4) IN ((1,2), (3,4));</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT (3,4) IN ((1,2), (3,5));</code></strong>
        -&gt; 0
</pre><p>
            You should never mix quoted and unquoted values in an
            <code class="literal">IN()</code> list because the comparison rules
            for quoted values (such as strings) and unquoted values
            (such as numbers) differ. Mixing types may therefore lead to
            inconsistent results. For example, do not write an
            <code class="literal">IN()</code> expression like this:
          </p><pre data-lang="sql" class="programlisting">SELECT val1 FROM tbl1 WHERE val1 IN (1,2,'a');</pre><p>
            Instead, write it like this:
          </p><pre data-lang="sql" class="programlisting">SELECT val1 FROM tbl1 WHERE val1 IN ('1','2','a');</pre><p>
            Implicit type conversion may produce nonintuitive results:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'a' IN (0), 0 IN ('b');</code></strong>
        -&gt; 1, 1
</pre><p>
            In both cases, the comparison values are converted to
            floating-point values, yielding 0.0 in each case, and a
            comparison result of 1 (true).
          </p><p>
            The number of values in the <code class="literal">IN()</code> list is
            only limited by the
            <a class="link" href="server-administration.html#sysvar_max_allowed_packet"><code class="literal">max_allowed_packet</code></a> value.
          </p><p>
            To comply with the SQL standard, <code class="literal">IN()</code>
            returns <code class="literal">NULL</code> not only if the expression
            on the left hand side is <code class="literal">NULL</code>, but also
            if no match is found in the list and one of the expressions
            in the list is <code class="literal">NULL</code>.
          </p><p>
            <code class="literal">IN()</code> syntax can also be used to write
            certain types of subqueries. See
            <a class="xref" href="sql-statements.html#any-in-some-subqueries" title="13.2.11.3 Subqueries with ANY, IN, or SOME">Section 13.2.11.3, “Subqueries with ANY, IN, or SOME”</a>.
          </p></li><li class="listitem"><a name="operator_not-in"></a><p>
            <a class="indexterm" name="idm46444332331888"></a>

            <a class="link" href="functions.html#operator_not-in"><code class="literal"><em class="replaceable"><code>expr</code></em>
            NOT IN (<em class="replaceable"><code>value</code></em>,...)</code></a>
          </p><p>
            This is the same as <code class="literal">NOT
            (<em class="replaceable"><code>expr</code></em> IN
            (<em class="replaceable"><code>value</code></em>,...))</code>.
          </p></li><li class="listitem"><a name="function_interval"></a><p>
            <a class="indexterm" name="idm46444332322720"></a>

            <a class="link" href="functions.html#function_interval"><code class="literal">INTERVAL(<em class="replaceable"><code>N</code></em>,<em class="replaceable"><code>N1</code></em>,<em class="replaceable"><code>N2</code></em>,<em class="replaceable"><code>N3</code></em>,...)</code></a>
          </p><p>
            Returns <code class="literal">0</code> if <em class="replaceable"><code>N</code></em>
            &lt; <em class="replaceable"><code>N1</code></em>, <code class="literal">1</code> if
            <em class="replaceable"><code>N</code></em> &lt;
            <em class="replaceable"><code>N2</code></em> and so on or
            <code class="literal">-1</code> if <em class="replaceable"><code>N</code></em> is
            <code class="literal">NULL</code>. All arguments are treated as
            integers. It is required that <em class="replaceable"><code>N1</code></em>
            &lt; <em class="replaceable"><code>N2</code></em> &lt;
            <em class="replaceable"><code>N3</code></em> &lt; <code class="literal">...</code>
            &lt; <em class="replaceable"><code>Nn</code></em> for this function to work
            correctly. This is because a binary search is used (very
            fast).
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);</code></strong>
        -&gt; 3
mysql&gt; <strong class="userinput"><code>SELECT INTERVAL(10, 1, 10, 100, 1000);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT INTERVAL(22, 23, 30, 44, 200);</code></strong>
        -&gt; 0
</pre></li><li class="listitem"><a name="operator_is"></a><p>
            <a class="indexterm" name="idm46444332302352"></a>

            <a class="indexterm" name="idm46444332300864"></a>

            <a class="indexterm" name="idm46444332299376"></a>

            <a class="indexterm" name="idm46444332297888"></a>

            <a class="link" href="functions.html#operator_is"><code class="literal">IS
            <em class="replaceable"><code>boolean_value</code></em></code></a>
          </p><p>
            Tests a value against a boolean value, where
            <em class="replaceable"><code>boolean_value</code></em> can be
            <code class="literal">TRUE</code>, <code class="literal">FALSE</code>, or
            <code class="literal">UNKNOWN</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;</code></strong>
        -&gt; 1, 1, 1
</pre></li><li class="listitem"><a name="operator_is-not"></a><p>
            <a class="indexterm" name="idm46444332285264"></a>

            <a class="indexterm" name="idm46444332283776"></a>

            <a class="indexterm" name="idm46444332282288"></a>

            <a class="indexterm" name="idm46444332280800"></a>

            <a class="link" href="functions.html#operator_is-not"><code class="literal">IS NOT
            <em class="replaceable"><code>boolean_value</code></em></code></a>
          </p><p>
            Tests a value against a boolean value, where
            <em class="replaceable"><code>boolean_value</code></em> can be
            <code class="literal">TRUE</code>, <code class="literal">FALSE</code>, or
            <code class="literal">UNKNOWN</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;</code></strong>
        -&gt; 1, 1, 0
</pre></li><li class="listitem"><a name="operator_is-null"></a><p>
            <a class="indexterm" name="idm46444332268160"></a>

            <a class="indexterm" name="idm46444332266672"></a>

            <a class="link" href="functions.html#operator_is-null"><code class="literal">IS NULL</code></a>
          </p><p>
            Tests whether a value is <code class="literal">NULL</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;</code></strong>
        -&gt; 0, 0, 1
</pre><p>
            <a class="indexterm" name="idm46444332259072"></a>

            <a class="indexterm" name="idm46444332258000"></a>

            To work well with ODBC programs, MySQL supports the
            following extra features when using <a class="link" href="functions.html#operator_is-null"><code class="literal">IS
            NULL</code></a>:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If <a class="link" href="server-administration.html#sysvar_sql_auto_is_null"><code class="literal">sql_auto_is_null</code></a>
                variable is set to 1, then after a statement that
                successfully inserts an automatically generated
                <code class="literal">AUTO_INCREMENT</code> value, you can find
                that value by issuing a statement of the following form:
              </p><pre data-lang="sql" class="programlisting">SELECT * FROM <em class="replaceable"><code>tbl_name</code></em> WHERE <em class="replaceable"><code>auto_col</code></em> IS NULL
</pre><p>
                If the statement returns a row, the value returned is
                the same as if you invoked the
                <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>
                function. For details, including the return value after
                a multiple-row insert, see
                <a class="xref" href="functions.html#information-functions" title="12.15 Information Functions">Section 12.15, “Information Functions”</a>. If no
                <code class="literal">AUTO_INCREMENT</code> value was successfully
                inserted, the <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>
                statement returns no row.
              </p><p>
                The behavior of retrieving an
                <code class="literal">AUTO_INCREMENT</code> value by using an
                <a class="link" href="functions.html#operator_is-null"><code class="literal">IS NULL</code></a> comparison can be
                disabled by setting
                <a class="link" href="server-administration.html#sysvar_sql_auto_is_null"><code class="literal">sql_auto_is_null = 0</code></a>.
                See <a class="xref" href="server-administration.html#server-system-variables" title="5.1.8 Server System Variables">Section 5.1.8, “Server System Variables”</a>.
              </p><p>
                The default value of
                <a class="link" href="server-administration.html#sysvar_sql_auto_is_null"><code class="literal">sql_auto_is_null</code></a> is 0.
              </p></li><li class="listitem"><p>
                For <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> and
                <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> columns that are
                declared as <code class="literal">NOT NULL</code>, you can find
                the special date <code class="literal">'0000-00-00'</code> by
                using a statement like this:
              </p><pre data-lang="sql" class="programlisting">SELECT * FROM <em class="replaceable"><code>tbl_name</code></em> WHERE <em class="replaceable"><code>date_column</code></em> IS NULL
</pre><p>
                This is needed to get some ODBC applications to work
                because ODBC does not support a
                <code class="literal">'0000-00-00'</code> date value.
              </p><p>
                See
                <a class="ulink" href="https://dev.mysql.com/doc/connector-odbc/en/connector-odbc-usagenotes-functionality-last-insert-id.html" target="_top">Obtaining Auto-Increment Values</a>,
                and the description for the
                <code class="literal">FLAG_AUTO_IS_NULL</code> option at
                <a class="ulink" href="https://dev.mysql.com/doc/connector-odbc/en/connector-odbc-configuration-connection-parameters.html" target="_top">Connector/ODBC Connection Parameters</a>.
</p></li></ul>
</div>
</li><li class="listitem"><a name="operator_is-not-null"></a><p>
            <a class="indexterm" name="idm46444332225328"></a>

            <a class="indexterm" name="idm46444332223840"></a>

            <a class="link" href="functions.html#operator_is-null"><code class="literal">IS NOT NULL</code></a>
          </p><p>
            Tests whether a value is not <code class="literal">NULL</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;</code></strong>
        -&gt; 1, 1, 0
</pre></li><li class="listitem"><a name="function_isnull"></a><p>
            <a class="indexterm" name="idm46444332214080"></a>

            <a class="link" href="functions.html#function_isnull"><code class="literal">ISNULL(<em class="replaceable"><code>expr</code></em>)</code></a>
          </p><p>
            If <em class="replaceable"><code>expr</code></em> is
            <code class="literal">NULL</code>,
            <a class="link" href="functions.html#function_isnull"><code class="literal">ISNULL()</code></a> returns
            <code class="literal">1</code>, otherwise it returns
            <code class="literal">0</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ISNULL(1+1);</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT ISNULL(1/0);</code></strong>
        -&gt; 1
</pre><p>
            <a class="link" href="functions.html#function_isnull"><code class="literal">ISNULL()</code></a> can be used instead
            of <a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a> to test
            whether a value is <code class="literal">NULL</code>. (Comparing a
            value to <code class="literal">NULL</code> using
            <a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a> always
            yields <code class="literal">NULL</code>.)
          </p><p>
            The <a class="link" href="functions.html#function_isnull"><code class="literal">ISNULL()</code></a> function shares
            some special behaviors with the
            <a class="link" href="functions.html#operator_is-null"><code class="literal">IS NULL</code></a>
            comparison operator. See the description of
            <a class="link" href="functions.html#operator_is-null"><code class="literal">IS NULL</code></a>.
          </p></li><li class="listitem"><a name="function_least"></a><p>
            <a class="indexterm" name="idm46444332189696"></a>

            <a class="link" href="functions.html#function_least"><code class="literal">LEAST(<em class="replaceable"><code>value1</code></em>,<em class="replaceable"><code>value2</code></em>,...)</code></a>
          </p><p>
            With two or more arguments, returns the smallest
            (minimum-valued) argument. The arguments are compared using
            the following rules:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If any argument is <code class="literal">NULL</code>, the result
                is <code class="literal">NULL</code>. No comparison is needed.
              </p></li><li class="listitem"><p>
                If all arguments are integer-valued, they are compared
                as integers.
              </p></li><li class="listitem"><p>
                If at least one argument is double precision, they are
                compared as double-precision values. Otherwise, if at
                least one argument is a
                <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> value, they are
                compared as <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a>
                values.
              </p></li><li class="listitem"><p>
                If the arguments comprise a mix of numbers and strings,
                they are compared as strings.
              </p></li><li class="listitem"><p>
                If any argument is a nonbinary (character) string, the
                arguments are compared as nonbinary strings.
              </p></li><li class="listitem"><p>
                In all other cases, the arguments are compared as binary
                strings.
</p></li></ul>
</div>
<p>
            The return type of <a class="link" href="functions.html#function_least"><code class="literal">LEAST()</code></a> is
            the aggregated type of the comparison argument types.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LEAST(2,0);</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT LEAST(34.0,3.0,5.0,767.0);</code></strong>
        -&gt; 3.0
mysql&gt; <strong class="userinput"><code>SELECT LEAST('B','A','C');</code></strong>
        -&gt; 'A'
</pre></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="logical-operators"></a>12.3.3 Logical Operators</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444332167552"></a><a class="indexterm" name="idm46444332166480"></a>
<div class="table">
<a name="idm46444332164992"></a><p class="title"><b>Table 12.4 Logical Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists logical operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_and"><code class="literal">AND</code>, <code class="literal">&amp;&amp;</code></a></td>
<td>
      Logical AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not"><code class="literal">NOT</code>, <code class="literal">!</code></a></td>
<td>
      Negates value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_or"><code class="literal">OR</code>, <code class="literal">||</code></a></td>
<td>
      Logical OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_xor"><code class="literal">XOR</code></a></td>
<td>
      Logical XOR
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
        In SQL, all logical operators evaluate to
        <code class="literal">TRUE</code>, <code class="literal">FALSE</code>, or
        <code class="literal">NULL</code> (<code class="literal">UNKNOWN</code>). In MySQL,
        these are implemented as 1 (<code class="literal">TRUE</code>), 0
        (<code class="literal">FALSE</code>), and <code class="literal">NULL</code>. Most of
        this is common to different SQL database servers, although some
        servers may return any nonzero value for
        <code class="literal">TRUE</code>.
      </p><p>
        MySQL evaluates any nonzero, non-<code class="literal">NULL</code> value
        to <code class="literal">TRUE</code>. For example, the following
        statements all assess to <code class="literal">TRUE</code>:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 10 IS TRUE;</code></strong>
-&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT -10 IS TRUE;</code></strong>
-&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 'string' IS NOT NULL;</code></strong>
-&gt; 1
</pre>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_not"></a><p>
            <a class="indexterm" name="idm46444332127824"></a>

            <a class="indexterm" name="idm46444332126368"></a>

            <a class="link" href="functions.html#operator_not"><code class="literal">NOT</code></a>,
            <a class="link" href="functions.html#operator_not"><code class="literal">!</code></a>
          </p><p>
            Logical NOT. Evaluates to <code class="literal">1</code> if the
            operand is <code class="literal">0</code>, to <code class="literal">0</code> if
            the operand is nonzero, and <code class="literal">NOT NULL</code>
            returns <code class="literal">NULL</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT NOT 10;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT NOT 0;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT NOT NULL;</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT ! (1+1);</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT ! 1+1;</code></strong>
        -&gt; 1
</pre><p>
            The last example produces <code class="literal">1</code> because the
            expression evaluates the same way as
            <code class="literal">(!1)+1</code>.
          </p><p>
            The <a class="link" href="functions.html#operator_not"><code class="literal">!</code></a>, operator
            is a nonstandard MySQL extension. As of MySQL 8.0.17, this
            operator is deprecated and support for it will be removed in
            a future MySQL version. Applications should be adjusted to
            use the standard SQL <a class="link" href="functions.html#operator_not"><code class="literal">NOT</code></a>
            operator.
          </p></li><li class="listitem"><a name="operator_and"></a><p>
            <a class="indexterm" name="idm46444332104096"></a>

            <a class="indexterm" name="idm46444332102640"></a>

            <a class="link" href="functions.html#operator_and"><code class="literal">AND</code></a>,
            <a class="link" href="functions.html#operator_and"><code class="literal">&amp;&amp;</code></a>
          </p><p>
            Logical AND. Evaluates to <code class="literal">1</code> if all
            operands are nonzero and not <code class="literal">NULL</code>, to
            <code class="literal">0</code> if one or more operands are
            <code class="literal">0</code>, otherwise <code class="literal">NULL</code> is
            returned.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 AND 1;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 1 AND 0;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 1 AND NULL;</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT 0 AND NULL;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT NULL AND 0;</code></strong>
        -&gt; 0
</pre><p>
            The <a class="link" href="functions.html#operator_and"><code class="literal">&amp;&amp;</code></a>,
            operator is a nonstandard MySQL extension. As of MySQL
            8.0.17, this operator is deprecated and support for it will
            be removed in a future MySQL version. Applications should be
            adjusted to use the standard SQL
            <a class="link" href="functions.html#operator_and"><code class="literal">AND</code></a> operator.
          </p></li><li class="listitem"><a name="operator_or"></a><p>
            <a class="indexterm" name="idm46444332082160"></a>

            <a class="indexterm" name="idm46444332080704"></a>

            <a class="link" href="functions.html#operator_or"><code class="literal">OR</code></a>,
            <a class="link" href="functions.html#operator_or"><code class="literal">||</code></a>
          </p><p>
            Logical OR. When both operands are
            non-<code class="literal">NULL</code>, the result is
            <code class="literal">1</code> if any operand is nonzero, and
            <code class="literal">0</code> otherwise. With a
            <code class="literal">NULL</code> operand, the result is
            <code class="literal">1</code> if the other operand is nonzero, and
            <code class="literal">NULL</code> otherwise. If both operands are
            <code class="literal">NULL</code>, the result is
            <code class="literal">NULL</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 OR 1;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 1 OR 0;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 0 OR 0;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 0 OR NULL;</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT 1 OR NULL;</code></strong>
        -&gt; 1
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
              If the <a class="link" href="server-administration.html#sqlmode_pipes_as_concat"><code class="literal">PIPES_AS_CONCAT</code></a>
              SQL mode is enabled,
              <a class="link" href="functions.html#operator_or"><code class="literal">||</code></a> signifies
              the SQL-standard string concatenation operator (like
              <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a>).
</p>
</div>
<p>
            The <a class="link" href="functions.html#operator_or"><code class="literal">||</code></a>, operator
            is a nonstandard MySQL extension. As of MySQL 8.0.17, this
            operator is deprecated and support for it will be removed in
            a future MySQL version. Applications should be adjusted to
            use the standard SQL <a class="link" href="functions.html#operator_or"><code class="literal">OR</code></a>
            operator. Exception: Deprecation does not apply if
            <a class="link" href="server-administration.html#sqlmode_pipes_as_concat"><code class="literal">PIPES_AS_CONCAT</code></a> is enabled
            because, in that case,
            <a class="link" href="functions.html#operator_or"><code class="literal">||</code></a> signifies
            string concatentation.
          </p></li><li class="listitem"><a name="operator_xor"></a><p>
            <a class="indexterm" name="idm46444332051584"></a>

            <a class="link" href="functions.html#operator_xor"><code class="literal">XOR</code></a>
          </p><p>
            Logical XOR. Returns <code class="literal">NULL</code> if either
            operand is <code class="literal">NULL</code>. For
            non-<code class="literal">NULL</code> operands, evaluates to
            <code class="literal">1</code> if an odd number of operands is
            nonzero, otherwise <code class="literal">0</code> is returned.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 XOR 1;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 1 XOR 0;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 1 XOR NULL;</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT 1 XOR 1 XOR 1;</code></strong>
        -&gt; 1
</pre><p>
            <code class="literal">a XOR b</code> is mathematically equal to
            <code class="literal">(a AND (NOT b)) OR ((NOT a) and b)</code>.
</p></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="assignment-operators"></a>12.3.4 Assignment Operators</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444332035456"></a><a class="indexterm" name="idm46444332034384"></a>
<div class="table">
<a name="idm46444332032896"></a><p class="title"><b>Table 12.5 Assignment Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists assignment operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a></td>
<td>
      Assign a value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_assign-equal"><code class="literal">=</code></a></td>
<td>
      Assign a value (as part of a
      <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
      statement, or as part of the <code class="literal">SET</code> clause in an
      <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement)
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_assign-value"></a><p>
            <a class="indexterm" name="idm46444332014560"></a>

            <a class="indexterm" name="idm46444332013472"></a>

            <a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a>
          </p><p>
            Assignment operator. Causes the user variable on the left
            hand side of the operator to take on the value to its right.
            The value on the right hand side may be a literal value,
            another variable storing a value, or any legal expression
            that yields a scalar value, including the result of a query
            (provided that this value is a scalar value). You can
            perform multiple assignments in the same
            <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
            statement. You can perform multiple assignments in the same
            statement.
          </p><p>
            Unlike
            <a class="link" href="functions.html#operator_assign-equal"><code class="literal">=</code></a>, the
            <a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a>
            operator is never interpreted as a comparison operator. This
            means you can use
            <a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a> in
            any valid SQL statement (not just in
            <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
            statements) to assign a value to a variable.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2;</code></strong>
        -&gt; NULL, NULL
mysql&gt; <strong class="userinput"><code>SELECT @var1 := 1, @var2;</code></strong>
        -&gt; 1, NULL
mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2;</code></strong>
        -&gt; 1, NULL
mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2 := @var1;</code></strong>
        -&gt; 1, 1
mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2;</code></strong>
        -&gt; 1, 1

mysql&gt; <strong class="userinput"><code>SELECT @var1:=COUNT(*) FROM t1;</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT @var1;</code></strong>
        -&gt; 4
</pre><p>
            You can make value assignments using
            <a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a> in
            other statements besides
            <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>, such as
            <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a>, as shown here:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT @var1;</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT * FROM t1;</code></strong>
        -&gt; 1, 3, 5, 7

mysql&gt; <strong class="userinput"><code>UPDATE t1 SET c1 = 2 WHERE c1 = @var1:= 1;</code></strong>
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT @var1;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT * FROM t1;</code></strong>
        -&gt; 2, 3, 5, 7
</pre><p>
            While it is also possible both to set and to read the value
            of the same variable in a single SQL statement using the
            <a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a>
            operator, this is not recommended.
            <a class="xref" href="language-structure.html#user-variables" title="9.4 User-Defined Variables">Section 9.4, “User-Defined Variables”</a>, explains why you should
            avoid doing this.
          </p></li><li class="listitem"><a name="operator_assign-equal"></a><p>
            <a class="indexterm" name="idm46444331980848"></a>

            <a class="indexterm" name="idm46444331979776"></a>

            <a class="indexterm" name="idm46444331978320"></a>

            <a class="link" href="functions.html#operator_assign-equal"><code class="literal">=</code></a>
          </p><p>
            This operator is used to perform value assignments in two
            cases, described in the next two paragraphs.
          </p><p>
            Within a
            <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
            statement, <code class="literal">=</code> is treated as an assignment
            operator that causes the user variable on the left hand side
            of the operator to take on the value to its right. (In other
            words, when used in a
            <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
            statement, <code class="literal">=</code> is treated identically to
            <a class="link" href="functions.html#operator_assign-value"><code class="literal">:=</code></a>.)
            The value on the right hand side may be a literal value,
            another variable storing a value, or any legal expression
            that yields a scalar value, including the result of a query
            (provided that this value is a scalar value). You can
            perform multiple assignments in the same
            <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>
            statement.
          </p><p>
            In the <code class="literal">SET</code> clause of an
            <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement,
            <code class="literal">=</code> also acts as an assignment operator; in
            this case, however, it causes the column named on the left
            hand side of the operator to assume the value given to the
            right, provided any <code class="literal">WHERE</code> conditions that
            are part of the <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> are
            met. You can make multiple assignments in the same
            <code class="literal">SET</code> clause of an
            <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement.
          </p><p>
            In any other context, <code class="literal">=</code> is treated as a
            <a class="link" href="functions.html#operator_equal">comparison operator</a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2;</code></strong>
        -&gt; NULL, NULL
mysql&gt; <strong class="userinput"><code>SELECT @var1 := 1, @var2;</code></strong>
        -&gt; 1, NULL
mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2;</code></strong>
        -&gt; 1, NULL
mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2 := @var1;</code></strong>
        -&gt; 1, 1
mysql&gt; <strong class="userinput"><code>SELECT @var1, @var2;</code></strong>
        -&gt; 1, 1
</pre><p>
            For more information, see <a class="xref" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment">Section 13.7.6.1, “SET Syntax for Variable Assignment”</a>,
            <a class="xref" href="sql-statements.html#update" title="13.2.13 UPDATE Statement">Section 13.2.13, “UPDATE Statement”</a>, and <a class="xref" href="sql-statements.html#subqueries" title="13.2.11 Subqueries">Section 13.2.11, “Subqueries”</a>.
</p></li></ul>
</div>

</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="control-flow-functions"></a>12.4 Control Flow Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444331947616"></a><a class="indexterm" name="idm46444331946544"></a>
<div class="table">
<a name="idm46444331945056"></a><p class="title"><b>Table 12.6 Flow Control Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists flow control operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_case"><code class="literal">CASE</code></a></td>
<td>
      Case operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_if"><code class="literal">IF()</code></a></td>
<td>
      If/else construct
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ifnull"><code class="literal">IFNULL()</code></a></td>
<td>
      Null if/else construct
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_nullif"><code class="literal">NULLIF()</code></a></td>
<td>
      Return NULL if expr1 = expr2
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_case"></a><p>
          <a class="indexterm" name="idm46444331921760"></a>

          <a class="link" href="functions.html#operator_case"><code class="literal">CASE
          <em class="replaceable"><code>value</code></em> WHEN
          [<em class="replaceable"><code>compare_value</code></em>] THEN
          <em class="replaceable"><code>result</code></em> [WHEN
          [<em class="replaceable"><code>compare_value</code></em>] THEN
          <em class="replaceable"><code>result</code></em> ...] [ELSE
          <em class="replaceable"><code>result</code></em>] END</code></a>
        </p><p>
          <a class="link" href="functions.html#operator_case"><code class="literal">CASE WHEN
          [<em class="replaceable"><code>condition</code></em>] THEN
          <em class="replaceable"><code>result</code></em> [WHEN
          [<em class="replaceable"><code>condition</code></em>] THEN
          <em class="replaceable"><code>result</code></em> ...] [ELSE
          <em class="replaceable"><code>result</code></em>] END</code></a>
        </p><p>
          The first <a class="link" href="functions.html#operator_case"><code class="literal">CASE</code></a> syntax returns the
          <em class="replaceable"><code>result</code></em> for the first
          <code class="literal"><em class="replaceable"><code>value</code></em>=<em class="replaceable"><code>compare_value</code></em></code>
          comparison that is true. The second syntax returns the result
          for the first condition that is true. If no comparison or
          condition is true, the result after <code class="literal">ELSE</code> is
          returned, or <code class="literal">NULL</code> if there is no
          <code class="literal">ELSE</code> part.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The syntax of the <a class="link" href="functions.html#operator_case"><code class="literal">CASE</code></a>
            <span class="emphasis"><em>expr</em></span> described here differs slightly
            from that of the SQL <a class="link" href="sql-statements.html#case" title="13.6.5.1 CASE Statement"><code class="literal">CASE</code></a>
            <span class="emphasis"><em>statement</em></span> described in
            <a class="xref" href="sql-statements.html#case" title="13.6.5.1 CASE Statement">Section 13.6.5.1, “CASE Statement”</a>, for use inside stored programs. The
            <a class="link" href="sql-statements.html#case" title="13.6.5.1 CASE Statement"><code class="literal">CASE</code></a> statement cannot have an
            <code class="literal">ELSE NULL</code> clause, and it is terminated
            with <code class="literal">END CASE</code> instead of
            <code class="literal">END</code>.
</p>
</div>
<p>
          The return type of a <a class="link" href="functions.html#operator_case"><code class="literal">CASE</code></a>
          expression result is the aggregated type of all result values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If all types are numeric, the aggregated type is also
              numeric:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  If at least one argument is double precision, the
                  result is double precision.
                </p></li><li class="listitem"><p>
                  Otherwise, if at least one argument is
                  <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a>, the result is
                  <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a>.
                </p></li><li class="listitem"><p>
                  Otherwise, the result is an integer type (with one
                  exception):
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
                      If all integer types are all signed or all
                      unsigned, the result is the same sign and the
                      precision is the highest of all specified integer
                      types (that is,
                      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">TINYINT</code></a>,
                      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">SMALLINT</code></a>,
                      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">MEDIUMINT</code></a>,
                      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a>, or
                      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>).
                    </p></li><li class="listitem"><p>
                      If there is a combination of signed and unsigned
                      integer types, the result is signed and the
                      precision may be higher. For example, if the types
                      are signed <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a> and
                      unsigned <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a>, the
                      result is signed
                      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>.
                    </p></li><li class="listitem"><p>
                      The exception is unsigned
                      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> combined
                      with any signed integer type. The result is
                      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> with
                      sufficient precision and scale 0.
</p></li></ul>
</div>
</li></ul>
</div>
</li><li class="listitem"><p>
              If all types are <a class="link" href="data-types.html#bit-type" title="11.1.5 Bit-Value Type - BIT"><code class="literal">BIT</code></a>, the
              result is <a class="link" href="data-types.html#bit-type" title="11.1.5 Bit-Value Type - BIT"><code class="literal">BIT</code></a>. Otherwise,
              <a class="link" href="data-types.html#bit-type" title="11.1.5 Bit-Value Type - BIT"><code class="literal">BIT</code></a> arguments are treated
              similar to <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>.
            </p></li><li class="listitem"><p>
              If all types are <a class="link" href="data-types.html#year" title="11.2.4 The YEAR Type"><code class="literal">YEAR</code></a>, the
              result is <a class="link" href="data-types.html#year" title="11.2.4 The YEAR Type"><code class="literal">YEAR</code></a>. Otherwise,
              <code class="literal">YEAR</code> arguments are treated similar to
              <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a>.
            </p></li><li class="listitem"><p>
              If all types are character string
              (<a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a> or
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>), the result is
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a> with maximum length
              determined by the longest character length of the
              operands.
            </p></li><li class="listitem"><p>
              If all types are character or binary string, the result is
              <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>.
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#set" title="11.3.6 The SET Type"><code class="literal">SET</code></a> and
              <a class="link" href="data-types.html#enum" title="11.3.5 The ENUM Type"><code class="literal">ENUM</code></a> are treated similar to
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>; the result is
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>.
            </p></li><li class="listitem"><p>
              If all types are <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a>, the
              result is <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a>.
            </p></li><li class="listitem"><p>
              If all types are temporal, the result is temporal:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  If all temporal types are
                  <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a>,
                  <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a>, or
                  <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a>, the result
                  is <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a>,
                  <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a>, or
                  <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a>,
                  respectively.
                </p></li><li class="listitem"><p>
                  Otherwise, for a mix of temporal types, the result is
                  <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>.
</p></li></ul>
</div>
</li><li class="listitem"><p>
              If all types are <code class="literal">GEOMETRY</code>, the result
              is <code class="literal">GEOMETRY</code>.
            </p></li><li class="listitem"><p>
              If any type is <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a>, the
              result is <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a>.
            </p></li><li class="listitem"><p>
              For all other type combinations, the result is
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>.
            </p></li><li class="listitem"><p>
              Literal <code class="literal">NULL</code> operands are ignored for
              type aggregation.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CASE 1 WHEN 1 THEN 'one'</code></strong>
    -&gt;     <strong class="userinput"><code>WHEN 2 THEN 'two' ELSE 'more' END;</code></strong>
        -&gt; 'one'
mysql&gt; <strong class="userinput"><code>SELECT CASE WHEN 1&gt;0 THEN 'true' ELSE 'false' END;</code></strong>
        -&gt; 'true'
mysql&gt; <strong class="userinput"><code>SELECT CASE BINARY 'B'</code></strong>
    -&gt;     <strong class="userinput"><code>WHEN 'a' THEN 1 WHEN 'b' THEN 2 END;</code></strong>
        -&gt; NULL
</pre></li><li class="listitem"><a name="function_if"></a><p>
          <a class="indexterm" name="idm46444331816832"></a>

          <a class="link" href="functions.html#function_if"><code class="literal">IF(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>,<em class="replaceable"><code>expr3</code></em>)</code></a>
        </p><p>
          If <em class="replaceable"><code>expr1</code></em> is <code class="literal">TRUE</code>
          (<code class="literal"><em class="replaceable"><code>expr1</code></em> &lt;&gt;
          0</code> and <code class="literal"><em class="replaceable"><code>expr1</code></em>
          &lt;&gt; NULL</code>), <a class="link" href="functions.html#function_if"><code class="literal">IF()</code></a>
          returns <em class="replaceable"><code>expr2</code></em>. Otherwise, it
          returns <em class="replaceable"><code>expr3</code></em>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            There is also an <a class="link" href="sql-statements.html#if" title="13.6.5.2 IF Statement"><code class="literal">IF</code></a>
            <span class="emphasis"><em>statement</em></span>, which differs from the
            <a class="link" href="functions.html#function_if"><code class="literal">IF()</code></a>
            <span class="emphasis"><em>function</em></span> described here. See
            <a class="xref" href="sql-statements.html#if" title="13.6.5.2 IF Statement">Section 13.6.5.2, “IF Statement”</a>.
</p>
</div>
<p>
          If only one of <em class="replaceable"><code>expr2</code></em> or
          <em class="replaceable"><code>expr3</code></em> is explicitly
          <code class="literal">NULL</code>, the result type of the
          <a class="link" href="functions.html#function_if"><code class="literal">IF()</code></a> function is the type of
          the non-<code class="literal">NULL</code> expression.
        </p><p>
          The default return type of <a class="link" href="functions.html#function_if"><code class="literal">IF()</code></a>
          (which may matter when it is stored into a temporary table) is
          calculated as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If <em class="replaceable"><code>expr2</code></em> or
              <em class="replaceable"><code>expr3</code></em> produce a string, the
              result is a string.
            </p><p>
              If <em class="replaceable"><code>expr2</code></em> and
              <em class="replaceable"><code>expr3</code></em> are both strings, the
              result is case-sensitive if either string is case
              sensitive.
            </p></li><li class="listitem"><p>
              If <em class="replaceable"><code>expr2</code></em> or
              <em class="replaceable"><code>expr3</code></em> produce a floating-point
              value, the result is a floating-point value.
            </p></li><li class="listitem"><p>
              If <em class="replaceable"><code>expr2</code></em> or
              <em class="replaceable"><code>expr3</code></em> produce an integer, the
              result is an integer.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT IF(1&gt;2,2,3);</code></strong>
        -&gt; 3
mysql&gt; <strong class="userinput"><code>SELECT IF(1&lt;2,'yes','no');</code></strong>
        -&gt; 'yes'
mysql&gt; <strong class="userinput"><code>SELECT IF(STRCMP('test','test1'),'no','yes');</code></strong>
        -&gt; 'no'
</pre></li><li class="listitem"><a name="function_ifnull"></a><p>
          <a class="indexterm" name="idm46444331782048"></a>

          <a class="indexterm" name="idm46444331780560"></a>

          <a class="link" href="functions.html#function_ifnull"><code class="literal">IFNULL(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
        </p><p>
          If <em class="replaceable"><code>expr1</code></em> is not
          <code class="literal">NULL</code>,
          <a class="link" href="functions.html#function_ifnull"><code class="literal">IFNULL()</code></a> returns
          <em class="replaceable"><code>expr1</code></em>; otherwise it returns
          <em class="replaceable"><code>expr2</code></em>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT IFNULL(1,0);</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT IFNULL(NULL,10);</code></strong>
        -&gt; 10
mysql&gt; <strong class="userinput"><code>SELECT IFNULL(1/0,10);</code></strong>
        -&gt; 10
mysql&gt; <strong class="userinput"><code>SELECT IFNULL(1/0,'yes');</code></strong>
        -&gt; 'yes'
</pre><p>
          The default return type of
          <a class="link" href="functions.html#function_ifnull"><code class="literal">IFNULL(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
          is the more <span class="quote">“<span class="quote">general</span>”</span> of the two expressions, in
          the order <code class="literal">STRING</code>, <code class="literal">REAL</code>,
          or <code class="literal">INTEGER</code>. Consider the case of a table
          based on expressions or where MySQL must internally store a
          value returned by <a class="link" href="functions.html#function_ifnull"><code class="literal">IFNULL()</code></a> in a
          temporary table:
        </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>CREATE TABLE tmp SELECT IFNULL(1,'test') AS test;</code></strong>
mysql&gt; <strong class="userinput"><code>DESCRIBE tmp;</code></strong>
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| test  | varbinary(4) | NO   |     |         |       |
+-------+--------------+------+-----+---------+-------+
</pre><p>
          In this example, the type of the <code class="literal">test</code>
          column is <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY(4)</code></a> (a
          string type).
        </p></li><li class="listitem"><a name="function_nullif"></a><p>
          <a class="indexterm" name="idm46444331753680"></a>

          <a class="link" href="functions.html#function_nullif"><code class="literal">NULLIF(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
        </p><p>
          Returns <code class="literal">NULL</code> if
          <code class="literal"><em class="replaceable"><code>expr1</code></em> =
          <em class="replaceable"><code>expr2</code></em></code> is true, otherwise
          returns <em class="replaceable"><code>expr1</code></em>. This is the same as
          <a class="link" href="functions.html#operator_case"><code class="literal">CASE WHEN
          <em class="replaceable"><code>expr1</code></em> =
          <em class="replaceable"><code>expr2</code></em> THEN NULL ELSE
          <em class="replaceable"><code>expr1</code></em> END</code></a>.
        </p><p>
          The return value has the same type as the first argument.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT NULLIF(1,1);</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT NULLIF(1,2);</code></strong>
        -&gt; 1
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            MySQL evaluates <em class="replaceable"><code>expr1</code></em> twice if
            the arguments are not equal.
</p>
</div>
</li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="numeric-functions"></a>12.5 Numeric Functions and Operators</h2>

</div>

</div>

</div>

<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#arithmetic-functions">12.5.1 Arithmetic Operators</a></span></dt><dt><span class="section"><a href="functions.html#mathematical-functions">12.5.2 Mathematical Functions</a></span></dt></dl>
</div>

<div class="table">
<a name="idm46444331737104"></a><p class="title"><b>Table 12.7 Numeric Functions and Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists numeric functions and operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_mod"><code class="literal">%</code>, <code class="literal">MOD</code></a></td>
<td>
      Modulo operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_times"><code class="literal">*</code></a></td>
<td>
      Multiplication operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a></td>
<td>
      Addition operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a></td>
<td>
      Minus operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_unary-minus"><code class="literal">-</code></a></td>
<td>
      Change the sign of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_divide"><code class="literal">/</code></a></td>
<td>
      Division operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_abs"><code class="literal">ABS()</code></a></td>
<td>
      Return the absolute value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_acos"><code class="literal">ACOS()</code></a></td>
<td>
      Return the arc cosine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asin"><code class="literal">ASIN()</code></a></td>
<td>
      Return the arc sine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_atan"><code class="literal">ATAN()</code></a></td>
<td>
      Return the arc tangent
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_atan2"><code class="literal">ATAN2()</code>, <code class="literal">ATAN()</code></a></td>
<td>
      Return the arc tangent of the two arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ceil"><code class="literal">CEIL()</code></a></td>
<td>
      Return the smallest integer value not less than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ceiling"><code class="literal">CEILING()</code></a></td>
<td>
      Return the smallest integer value not less than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_conv"><code class="literal">CONV()</code></a></td>
<td>
      Convert numbers between different number bases
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cos"><code class="literal">COS()</code></a></td>
<td>
      Return the cosine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cot"><code class="literal">COT()</code></a></td>
<td>
      Return the cotangent
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_crc32"><code class="literal">CRC32()</code></a></td>
<td>
      Compute a cyclic redundancy check value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_degrees"><code class="literal">DEGREES()</code></a></td>
<td>
      Convert radians to degrees
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_div"><code class="literal">DIV</code></a></td>
<td>
      Integer division
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_exp"><code class="literal">EXP()</code></a></td>
<td>
      Raise to the power of
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_floor"><code class="literal">FLOOR()</code></a></td>
<td>
      Return the largest integer value not greater than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ln"><code class="literal">LN()</code></a></td>
<td>
      Return the natural logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log"><code class="literal">LOG()</code></a></td>
<td>
      Return the natural logarithm of the first argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log10"><code class="literal">LOG10()</code></a></td>
<td>
      Return the base-10 logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log2"><code class="literal">LOG2()</code></a></td>
<td>
      Return the base-2 logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mod"><code class="literal">MOD()</code></a></td>
<td>
      Return the remainder
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_pi"><code class="literal">PI()</code></a></td>
<td>
      Return the value of pi
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_pow"><code class="literal">POW()</code></a></td>
<td>
      Return the argument raised to the specified power
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_power"><code class="literal">POWER()</code></a></td>
<td>
      Return the argument raised to the specified power
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_radians"><code class="literal">RADIANS()</code></a></td>
<td>
      Return argument converted to radians
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a></td>
<td>
      Return a random floating-point value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a></td>
<td>
      Round the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sign"><code class="literal">SIGN()</code></a></td>
<td>
      Return the sign of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sin"><code class="literal">SIN()</code></a></td>
<td>
      Return the sine of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sqrt"><code class="literal">SQRT()</code></a></td>
<td>
      Return the square root of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_tan"><code class="literal">TAN()</code></a></td>
<td>
      Return the tangent of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_truncate"><code class="literal">TRUNCATE()</code></a></td>
<td>
      Truncate to specified number of decimal places
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="arithmetic-functions"></a>12.5.1 Arithmetic Operators</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444331609024"></a>
<div class="table">
<a name="idm46444331607536"></a><p class="title"><b>Table 12.8 Arithmetic Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists arithmetic operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_mod"><code class="literal">%</code>, <code class="literal">MOD</code></a></td>
<td>
      Modulo operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_times"><code class="literal">*</code></a></td>
<td>
      Multiplication operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a></td>
<td>
      Addition operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a></td>
<td>
      Minus operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_unary-minus"><code class="literal">-</code></a></td>
<td>
      Change the sign of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_divide"><code class="literal">/</code></a></td>
<td>
      Division operator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_div"><code class="literal">DIV</code></a></td>
<td>
      Integer division
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
        The usual arithmetic operators are available. The result is
        determined according to the following rules:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            In the case of
            <a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a>,
            <a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a>, and
            <a class="link" href="functions.html#operator_times"><code class="literal">*</code></a>, the result
            is calculated with <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>
            (64-bit) precision if both operands are integers.
          </p></li><li class="listitem"><p>
            If both operands are integers and any of them are unsigned,
            the result is an unsigned integer. For subtraction, if the
            <a class="link" href="server-administration.html#sqlmode_no_unsigned_subtraction"><code class="literal">NO_UNSIGNED_SUBTRACTION</code></a>
            SQL mode is enabled, the result is signed even if any
            operand is unsigned.
          </p></li><li class="listitem"><p>
            If any of the operands of a
            <a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a>,
            <a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a>,
            <a class="link" href="functions.html#operator_divide"><code class="literal">/</code></a>,
            <a class="link" href="functions.html#operator_times"><code class="literal">*</code></a>,
            <a class="link" href="functions.html#operator_mod"><code class="literal">%</code></a> is a real or
            string value, the precision of the result is the precision
            of the operand with the maximum precision.
          </p></li><li class="listitem"><p>
            In division performed with
            <a class="link" href="functions.html#operator_divide"><code class="literal">/</code></a>, the scale
            of the result when using two exact-value operands is the
            scale of the first operand plus the value of the
            <a class="link" href="server-administration.html#sysvar_div_precision_increment"><code class="literal">div_precision_increment</code></a>
            system variable (which is 4 by default). For example, the
            result of the expression <code class="literal">5.05 / 0.014</code> has
            a scale of six decimal places
            (<code class="literal">360.714286</code>).
</p></li></ul>
</div>
<p>
        These rules are applied for each operation, such that nested
        calculations imply the precision of each component. Hence,
        <code class="literal">(14620 / 9432456) / (24250 / 9432456)</code>,
        resolves first to <code class="literal">(0.0014) / (0.0026)</code>, with
        the final result having 8 decimal places
        (<code class="literal">0.60288653</code>).
      </p><p>
        Because of these rules and the way they are applied, care should
        be taken to ensure that components and subcomponents of a
        calculation use the appropriate level of precision. See
        <a class="xref" href="functions.html#cast-functions" title="12.10 Cast Functions and Operators">Section 12.10, “Cast Functions and Operators”</a>.
      </p><p>
        For information about handling of overflow in numeric expression
        evaluation, see <a class="xref" href="data-types.html#out-of-range-and-overflow" title="11.1.7 Out-of-Range and Overflow Handling">Section 11.1.7, “Out-of-Range and Overflow Handling”</a>.
      </p><p>
        Arithmetic operators apply to numbers. For other types of
        values, alternative operations may be available. For example, to
        add date values, use <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a>;
        see <a class="xref" href="functions.html#date-and-time-functions" title="12.6 Date and Time Functions">Section 12.6, “Date and Time Functions”</a>.
</p><a class="indexterm" name="idm46444331548704"></a><a class="indexterm" name="idm46444331547216"></a>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_plus"></a><p>
            <a class="indexterm" name="idm46444331543648"></a>

            <a class="indexterm" name="idm46444331542576"></a>

            <a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a>
          </p><p>
            Addition:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 3+5;</code></strong>
        -&gt; 8
</pre></li><li class="listitem"><a name="operator_minus"></a><p>
            <a class="indexterm" name="idm46444331533616"></a>

            <a class="indexterm" name="idm46444331532544"></a>

            <a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a>
          </p><p>
            Subtraction:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 3-5;</code></strong>
        -&gt; -2
</pre></li><li class="listitem"><a name="operator_unary-minus"></a><p>
            <a class="indexterm" name="idm46444331523648"></a>

            <a class="indexterm" name="idm46444331522576"></a>

            <a class="indexterm" name="idm46444331521088"></a>

            <a class="link" href="functions.html#operator_unary-minus"><code class="literal">-</code></a>
          </p><p>
            Unary minus. This operator changes the sign of the operand.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT - 2;</code></strong>
        -&gt; -2
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
              If this operator is used with a
              <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>, the return value is
              also a <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>. This means
              that you should avoid using <code class="literal">-</code> on
              integers that may have the value of
              −2<sup>63</sup>.
</p>
</div>
</li><li class="listitem"><a name="operator_times"></a><p>
            <a class="indexterm" name="idm46444331507504"></a>

            <a class="indexterm" name="idm46444331506432"></a>

            <a class="link" href="functions.html#operator_times"><code class="literal">*</code></a>
          </p><p>
            Multiplication:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 3*5;</code></strong>
        -&gt; 15
mysql&gt; <strong class="userinput"><code>SELECT 18014398509481984*18014398509481984.0;</code></strong>
        -&gt; 324518553658426726783156020576256.0
mysql&gt; <strong class="userinput"><code>SELECT 18014398509481984*18014398509481984;</code></strong>
        -&gt; out-of-range error
</pre><p>
            The last expression produces an error because the result of
            the integer multiplication exceeds the 64-bit range of
            <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> calculations. (See
            <a class="xref" href="data-types.html#numeric-types" title="11.1 Numeric Data Types">Section 11.1, “Numeric Data Types”</a>.)
          </p></li><li class="listitem"><a name="operator_divide"></a><p>
            <a class="indexterm" name="idm46444331493216"></a>

            <a class="indexterm" name="idm46444331492144"></a>

            <a class="link" href="functions.html#operator_divide"><code class="literal">/</code></a>
          </p><p>
            Division:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 3/5;</code></strong>
        -&gt; 0.60
</pre><p>
            Division by zero produces a <code class="literal">NULL</code> result:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 102/(1-1);</code></strong>
        -&gt; NULL
</pre><p>
            A division is calculated with
            <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> arithmetic only if
            performed in a context where its result is converted to an
            integer.
          </p></li><li class="listitem"><a name="operator_div"></a><p>
            <a class="indexterm" name="idm46444331477904"></a>

            <a class="link" href="functions.html#operator_div"><code class="literal">DIV</code></a>
          </p><p>
            Integer division. Discards from the division result any
            fractional part to the right of the decimal point.
          </p><p>
            If either operand has a noninteger type, the operands are
            converted to <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> and
            divided using <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a>
            arithmetic before converting the result to
            <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>. If the result exceeds
            <code class="literal">BIGINT</code> range, an error occurs.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 5 DIV 2, -5 DIV 2, 5 DIV -2, -5 DIV -2;</code></strong>
        -&gt; 2, -2, -2, 2
</pre></li><li class="listitem"><a name="operator_mod"></a><p>
            <a class="indexterm" name="idm46444331463088"></a>

            <a class="link" href="functions.html#operator_mod"><code class="literal"><em class="replaceable"><code>N</code></em>
            % <em class="replaceable"><code>M</code></em></code></a>,
            <a class="link" href="functions.html#operator_mod"><code class="literal"><em class="replaceable"><code>N</code></em>
            MOD <em class="replaceable"><code>M</code></em></code></a>
          </p><p>
            Modulo operation. Returns the remainder of
            <em class="replaceable"><code>N</code></em> divided by
            <em class="replaceable"><code>M</code></em>. For more information, see the
            description for the <a class="link" href="functions.html#function_mod"><code class="literal">MOD()</code></a>
            function in <a class="xref" href="functions.html#mathematical-functions" title="12.5.2 Mathematical Functions">Section 12.5.2, “Mathematical Functions”</a>.
</p></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="mathematical-functions"></a>12.5.2 Mathematical Functions</h3>

</div>

</div>

</div>

<div class="table">
<a name="idm46444331451936"></a><p class="title"><b>Table 12.9 Mathematical Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists mathematical functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_abs"><code class="literal">ABS()</code></a></td>
<td>
      Return the absolute value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_acos"><code class="literal">ACOS()</code></a></td>
<td>
      Return the arc cosine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asin"><code class="literal">ASIN()</code></a></td>
<td>
      Return the arc sine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_atan"><code class="literal">ATAN()</code></a></td>
<td>
      Return the arc tangent
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_atan2"><code class="literal">ATAN2()</code>, <code class="literal">ATAN()</code></a></td>
<td>
      Return the arc tangent of the two arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ceil"><code class="literal">CEIL()</code></a></td>
<td>
      Return the smallest integer value not less than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ceiling"><code class="literal">CEILING()</code></a></td>
<td>
      Return the smallest integer value not less than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_conv"><code class="literal">CONV()</code></a></td>
<td>
      Convert numbers between different number bases
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cos"><code class="literal">COS()</code></a></td>
<td>
      Return the cosine
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cot"><code class="literal">COT()</code></a></td>
<td>
      Return the cotangent
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_crc32"><code class="literal">CRC32()</code></a></td>
<td>
      Compute a cyclic redundancy check value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_degrees"><code class="literal">DEGREES()</code></a></td>
<td>
      Convert radians to degrees
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_exp"><code class="literal">EXP()</code></a></td>
<td>
      Raise to the power of
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_floor"><code class="literal">FLOOR()</code></a></td>
<td>
      Return the largest integer value not greater than the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ln"><code class="literal">LN()</code></a></td>
<td>
      Return the natural logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log"><code class="literal">LOG()</code></a></td>
<td>
      Return the natural logarithm of the first argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log10"><code class="literal">LOG10()</code></a></td>
<td>
      Return the base-10 logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_log2"><code class="literal">LOG2()</code></a></td>
<td>
      Return the base-2 logarithm of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mod"><code class="literal">MOD()</code></a></td>
<td>
      Return the remainder
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_pi"><code class="literal">PI()</code></a></td>
<td>
      Return the value of pi
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_pow"><code class="literal">POW()</code></a></td>
<td>
      Return the argument raised to the specified power
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_power"><code class="literal">POWER()</code></a></td>
<td>
      Return the argument raised to the specified power
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_radians"><code class="literal">RADIANS()</code></a></td>
<td>
      Return argument converted to radians
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a></td>
<td>
      Return a random floating-point value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a></td>
<td>
      Round the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sign"><code class="literal">SIGN()</code></a></td>
<td>
      Return the sign of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sin"><code class="literal">SIN()</code></a></td>
<td>
      Return the sine of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sqrt"><code class="literal">SQRT()</code></a></td>
<td>
      Return the square root of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_tan"><code class="literal">TAN()</code></a></td>
<td>
      Return the tangent of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_truncate"><code class="literal">TRUNCATE()</code></a></td>
<td>
      Truncate to specified number of decimal places
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
        All mathematical functions return <code class="literal">NULL</code> in the
        event of an error.
</p><a class="indexterm" name="idm46444331345888"></a><a class="indexterm" name="idm46444331344816"></a>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_abs"></a><p>
            <a class="indexterm" name="idm46444331340832"></a>

            <a class="link" href="functions.html#function_abs"><code class="literal">ABS(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the absolute value of <em class="replaceable"><code>X</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ABS(2);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT ABS(-32);</code></strong>
        -&gt; 32
</pre><p>
            This function is safe to use with
            <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> values.
          </p></li><li class="listitem"><a name="function_acos"></a><p>
            <a class="indexterm" name="idm46444331328608"></a>

            <a class="link" href="functions.html#function_acos"><code class="literal">ACOS(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the arc cosine of <em class="replaceable"><code>X</code></em>, that
            is, the value whose cosine is <em class="replaceable"><code>X</code></em>.
            Returns <code class="literal">NULL</code> if
            <em class="replaceable"><code>X</code></em> is not in the range
            <code class="literal">-1</code> to <code class="literal">1</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ACOS(1);</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT ACOS(1.0001);</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT ACOS(0);</code></strong>
        -&gt; 1.5707963267949
</pre></li><li class="listitem"><a name="function_asin"></a><p>
            <a class="indexterm" name="idm46444331314304"></a>

            <a class="link" href="functions.html#function_asin"><code class="literal">ASIN(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the arc sine of <em class="replaceable"><code>X</code></em>, that
            is, the value whose sine is <em class="replaceable"><code>X</code></em>.
            Returns <code class="literal">NULL</code> if
            <em class="replaceable"><code>X</code></em> is not in the range
            <code class="literal">-1</code> to <code class="literal">1</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ASIN(0.2);</code></strong>
        -&gt; 0.20135792079033
mysql&gt; <strong class="userinput"><code>SELECT ASIN('foo');</code></strong>

+-------------+
| ASIN('foo') |
+-------------+
|           0 |
+-------------+
1 row in set, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS;</code></strong>
+---------+------+-----------------------------------------+
| Level   | Code | Message                                 |
+---------+------+-----------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'foo' |
+---------+------+-----------------------------------------+
</pre></li><li class="listitem"><a name="function_atan"></a><p>
            <a class="indexterm" name="idm46444331299488"></a>

            <a class="link" href="functions.html#function_atan"><code class="literal">ATAN(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the arc tangent of <em class="replaceable"><code>X</code></em>,
            that is, the value whose tangent is
            <em class="replaceable"><code>X</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ATAN(2);</code></strong>
        -&gt; 1.1071487177941
mysql&gt; <strong class="userinput"><code>SELECT ATAN(-2);</code></strong>
        -&gt; -1.1071487177941
</pre></li><li class="listitem"><a name="function_atan2"></a><p>
            <a class="indexterm" name="idm46444331288352"></a>

            <a class="link" href="functions.html#function_atan2"><code class="literal">ATAN(<em class="replaceable"><code>Y</code></em>,<em class="replaceable"><code>X</code></em>)</code></a>,
            <a class="link" href="functions.html#function_atan2"><code class="literal">ATAN2(<em class="replaceable"><code>Y</code></em>,<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the arc tangent of the two variables
            <em class="replaceable"><code>X</code></em> and
            <em class="replaceable"><code>Y</code></em>. It is similar to calculating
            the arc tangent of <code class="literal"><em class="replaceable"><code>Y</code></em> /
            <em class="replaceable"><code>X</code></em></code>, except that the
            signs of both arguments are used to determine the quadrant
            of the result.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ATAN(-2,2);</code></strong>
        -&gt; -0.78539816339745
mysql&gt; <strong class="userinput"><code>SELECT ATAN2(PI(),0);</code></strong>
        -&gt; 1.5707963267949
</pre></li><li class="listitem"><a name="function_ceil"></a><p>
            <a class="indexterm" name="idm46444331272832"></a>

            <a class="link" href="functions.html#function_ceil"><code class="literal">CEIL(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            <a class="link" href="functions.html#function_ceil"><code class="literal">CEIL()</code></a> is a synonym for
            <a class="link" href="functions.html#function_ceiling"><code class="literal">CEILING()</code></a>.
          </p></li><li class="listitem"><a name="function_ceiling"></a><p>
            <a class="indexterm" name="idm46444331262560"></a>

            <a class="link" href="functions.html#function_ceiling"><code class="literal">CEILING(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the smallest integer value not less than
            <em class="replaceable"><code>X</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CEILING(1.23);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT CEILING(-1.23);</code></strong>
        -&gt; -1
</pre><p>
            For exact-value numeric arguments, the return value has an
            exact-value numeric type. For string or floating-point
            arguments, the return value has a floating-point type.
          </p></li><li class="listitem"><a name="function_conv"></a><p>
            <a class="indexterm" name="idm46444331251376"></a>

            <a class="link" href="functions.html#function_conv"><code class="literal">CONV(<em class="replaceable"><code>N</code></em>,<em class="replaceable"><code>from_base</code></em>,<em class="replaceable"><code>to_base</code></em>)</code></a>
          </p><p>
            Converts numbers between different number bases. Returns a
            string representation of the number
            <em class="replaceable"><code>N</code></em>, converted from base
            <em class="replaceable"><code>from_base</code></em> to base
            <em class="replaceable"><code>to_base</code></em>. Returns
            <code class="literal">NULL</code> if any argument is
            <code class="literal">NULL</code>. The argument
            <em class="replaceable"><code>N</code></em> is interpreted as an integer,
            but may be specified as an integer or a string. The minimum
            base is <code class="literal">2</code> and the maximum base is
            <code class="literal">36</code>. If
            <em class="replaceable"><code>from_base</code></em> is a negative number,
            <em class="replaceable"><code>N</code></em> is regarded as a signed number.
            Otherwise, <em class="replaceable"><code>N</code></em> is treated as
            unsigned. <a class="link" href="functions.html#function_conv"><code class="literal">CONV()</code></a> works with
            64-bit precision.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CONV('a',16,2);</code></strong>
        -&gt; '1010'
mysql&gt; <strong class="userinput"><code>SELECT CONV('6E',18,8);</code></strong>
        -&gt; '172'
mysql&gt; <strong class="userinput"><code>SELECT CONV(-17,10,-18);</code></strong>
        -&gt; '-H'
mysql&gt; <strong class="userinput"><code>SELECT CONV(10+'10'+'10'+X'0a',10,10);</code></strong>
        -&gt; '40'
</pre></li><li class="listitem"><a name="function_cos"></a><p>
            <a class="indexterm" name="idm46444331231344"></a>

            <a class="link" href="functions.html#function_cos"><code class="literal">COS(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the cosine of <em class="replaceable"><code>X</code></em>, where
            <em class="replaceable"><code>X</code></em> is given in radians.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COS(PI());</code></strong>
        -&gt; -1
</pre></li><li class="listitem"><a name="function_cot"></a><p>
            <a class="indexterm" name="idm46444331221104"></a>

            <a class="link" href="functions.html#function_cot"><code class="literal">COT(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the cotangent of <em class="replaceable"><code>X</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COT(12);</code></strong>
        -&gt; -1.5726734063977
mysql&gt; <strong class="userinput"><code>SELECT COT(0);</code></strong>
        -&gt; out-of-range error
</pre></li><li class="listitem"><a name="function_crc32"></a><p>
            <a class="indexterm" name="idm46444331210448"></a>

            <a class="link" href="functions.html#function_crc32"><code class="literal">CRC32(<em class="replaceable"><code>expr</code></em>)</code></a>
          </p><p>
            Computes a cyclic redundancy check value and returns a
            32-bit unsigned value. The result is <code class="literal">NULL</code>
            if the argument is <code class="literal">NULL</code>. The argument is
            expected to be a string and (if possible) is treated as one
            if it is not.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CRC32('MySQL');</code></strong>
        -&gt; 3259397556
mysql&gt; <strong class="userinput"><code>SELECT CRC32('mysql');</code></strong>
        -&gt; 2501908538
</pre></li><li class="listitem"><a name="function_degrees"></a><p>
            <a class="indexterm" name="idm46444331198608"></a>

            <a class="link" href="functions.html#function_degrees"><code class="literal">DEGREES(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the argument <em class="replaceable"><code>X</code></em>, converted
            from radians to degrees.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DEGREES(PI());</code></strong>
        -&gt; 180
mysql&gt; <strong class="userinput"><code>SELECT DEGREES(PI() / 2);</code></strong>
        -&gt; 90
</pre></li><li class="listitem"><a name="function_exp"></a><p>
            <a class="indexterm" name="idm46444331188080"></a>

            <a class="link" href="functions.html#function_exp"><code class="literal">EXP(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the value of <span class="emphasis"><em>e</em></span> (the base of
            natural logarithms) raised to the power of
            <em class="replaceable"><code>X</code></em>. The inverse of this function
            is <a class="link" href="functions.html#function_log"><code class="literal">LOG()</code></a> (using a single
            argument only) or <a class="link" href="functions.html#function_ln"><code class="literal">LN()</code></a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT EXP(2);</code></strong>
        -&gt; 7.3890560989307
mysql&gt; <strong class="userinput"><code>SELECT EXP(-2);</code></strong>
        -&gt; 0.13533528323661
mysql&gt; <strong class="userinput"><code>SELECT EXP(0);</code></strong>
        -&gt; 1
</pre></li><li class="listitem"><a name="function_floor"></a><p>
            <a class="indexterm" name="idm46444331173680"></a>

            <a class="link" href="functions.html#function_floor"><code class="literal">FLOOR(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the largest integer value not greater than
            <em class="replaceable"><code>X</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FLOOR(1.23), FLOOR(-1.23);</code></strong>
        -&gt; 1, -2
</pre><p>
            For exact-value numeric arguments, the return value has an
            exact-value numeric type. For string or floating-point
            arguments, the return value has a floating-point type.
          </p></li><li class="listitem"><p>
            <a class="link" href="functions.html#function_format"><code class="literal">FORMAT(<em class="replaceable"><code>X</code></em>,<em class="replaceable"><code>D</code></em>)</code></a>
          </p><p>
            Formats the number <em class="replaceable"><code>X</code></em> to a format
            like <code class="literal">'#,###,###.##'</code>, rounded to
            <em class="replaceable"><code>D</code></em> decimal places, and returns the
            result as a string. For details, see
            <a class="xref" href="functions.html#string-functions" title="12.7 String Functions and Operators">Section 12.7, “String Functions and Operators”</a>.
          </p></li><li class="listitem"><p>
            <a class="indexterm" name="idm46444331157728"></a>

            <a class="link" href="functions.html#function_hex"><code class="literal">HEX(N_or_S)</code></a>
          </p><p>
            This function can be used to obtain a hexadecimal
            representation of a decimal number or a string; the manner
            in which it does so varies according to the argument's
            type. See this function's description in
            <a class="xref" href="functions.html#string-functions" title="12.7 String Functions and Operators">Section 12.7, “String Functions and Operators”</a>, for details.
          </p></li><li class="listitem"><a name="function_ln"></a><p>
            <a class="indexterm" name="idm46444331151552"></a>

            <a class="link" href="functions.html#function_ln"><code class="literal">LN(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the natural logarithm of
            <em class="replaceable"><code>X</code></em>; that is, the
            base-<span class="emphasis"><em>e</em></span> logarithm of
            <em class="replaceable"><code>X</code></em>. If
            <em class="replaceable"><code>X</code></em> is less than or equal to 0.0E0,
            the function returns <code class="literal">NULL</code> and a warning
            <span class="quote">“<span class="quote">Invalid argument for logarithm</span>”</span> is reported.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LN(2);</code></strong>
        -&gt; 0.69314718055995
mysql&gt; <strong class="userinput"><code>SELECT LN(-2);</code></strong>
        -&gt; NULL
</pre><p>
            This function is synonymous with
            <a class="link" href="functions.html#function_log"><code class="literal">LOG(<em class="replaceable"><code>X</code></em>)</code></a>.
            The inverse of this function is the
            <a class="link" href="functions.html#function_exp"><code class="literal">EXP()</code></a> function.
          </p></li><li class="listitem"><a name="function_log"></a><p>
            <a class="indexterm" name="idm46444331134992"></a>

            <a class="link" href="functions.html#function_log"><code class="literal">LOG(<em class="replaceable"><code>X</code></em>)</code></a>,
            <a class="link" href="functions.html#function_log"><code class="literal">LOG(<em class="replaceable"><code>B</code></em>,<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            If called with one parameter, this function returns the
            natural logarithm of <em class="replaceable"><code>X</code></em>. If
            <em class="replaceable"><code>X</code></em> is less than or equal to 0.0E0,
            the function returns <code class="literal">NULL</code> and a warning
            <span class="quote">“<span class="quote">Invalid argument for logarithm</span>”</span> is reported.
          </p><p>
            The inverse of this function (when called with a single
            argument) is the <a class="link" href="functions.html#function_exp"><code class="literal">EXP()</code></a>
            function.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LOG(2);</code></strong>
        -&gt; 0.69314718055995
mysql&gt; <strong class="userinput"><code>SELECT LOG(-2);</code></strong>
        -&gt; NULL
</pre><p>
            If called with two parameters, this function returns the
            logarithm of <em class="replaceable"><code>X</code></em> to the base
            <em class="replaceable"><code>B</code></em>. If
            <em class="replaceable"><code>X</code></em> is less than or equal to 0, or
            if <em class="replaceable"><code>B</code></em> is less than or equal to 1,
            then <code class="literal">NULL</code> is returned.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LOG(2,65536);</code></strong>
        -&gt; 16
mysql&gt; <strong class="userinput"><code>SELECT LOG(10,100);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT LOG(1,100);</code></strong>
        -&gt; NULL
</pre><p>
            <a class="link" href="functions.html#function_log"><code class="literal">LOG(<em class="replaceable"><code>B</code></em>,<em class="replaceable"><code>X</code></em>)</code></a>
            is equivalent to
            <a class="link" href="functions.html#function_log"><code class="literal">LOG(<em class="replaceable"><code>X</code></em>) /
            LOG(<em class="replaceable"><code>B</code></em>)</code></a>.
          </p></li><li class="listitem"><a name="function_log2"></a><p>
            <a class="indexterm" name="idm46444331108400"></a>

            <a class="link" href="functions.html#function_log2"><code class="literal">LOG2(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the base-2 logarithm of
            <code class="literal"><em class="replaceable"><code>X</code></em></code>. If
            <em class="replaceable"><code>X</code></em> is less than or equal to 0.0E0,
            the function returns <code class="literal">NULL</code> and a warning
            <span class="quote">“<span class="quote">Invalid argument for logarithm</span>”</span> is reported.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LOG2(65536);</code></strong>
        -&gt; 16
mysql&gt; <strong class="userinput"><code>SELECT LOG2(-100);</code></strong>
        -&gt; NULL
</pre><p>
            <a class="link" href="functions.html#function_log2"><code class="literal">LOG2()</code></a> is useful for finding
            out how many bits a number requires for storage. This
            function is equivalent to the expression
            <a class="link" href="functions.html#function_log"><code class="literal">LOG(<em class="replaceable"><code>X</code></em>) /
            LOG(2)</code></a>.
          </p></li><li class="listitem"><a name="function_log10"></a><p>
            <a class="indexterm" name="idm46444331092368"></a>

            <a class="link" href="functions.html#function_log10"><code class="literal">LOG10(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the base-10 logarithm of
            <em class="replaceable"><code>X</code></em>. If
            <em class="replaceable"><code>X</code></em> is less than or equal to 0.0E0,
            the function returns <code class="literal">NULL</code> and a warning
            <span class="quote">“<span class="quote">Invalid argument for logarithm</span>”</span> is reported.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LOG10(2);</code></strong>
        -&gt; 0.30102999566398
mysql&gt; <strong class="userinput"><code>SELECT LOG10(100);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT LOG10(-100);</code></strong>
        -&gt; NULL
</pre><p>
            <a class="link" href="functions.html#function_log10"><code class="literal">LOG10(<em class="replaceable"><code>X</code></em>)</code></a>
            is equivalent to
            <a class="link" href="functions.html#function_log"><code class="literal">LOG(10,<em class="replaceable"><code>X</code></em>)</code></a>.
          </p></li><li class="listitem"><a name="function_mod"></a><p>
            <a class="indexterm" name="idm46444331075088"></a>

            <a class="indexterm" name="idm46444331074016"></a>

            <a class="indexterm" name="idm46444331072944"></a>

            <a class="indexterm" name="idm46444331071872"></a>

            <a class="indexterm" name="idm46444331070800"></a>

            <a class="link" href="functions.html#function_mod"><code class="literal">MOD(<em class="replaceable"><code>N</code></em>,<em class="replaceable"><code>M</code></em>)</code></a>,
            <a class="link" href="functions.html#operator_mod"><code class="literal"><em class="replaceable"><code>N</code></em>
            % <em class="replaceable"><code>M</code></em></code></a>,
            <a class="link" href="functions.html#operator_mod"><code class="literal"><em class="replaceable"><code>N</code></em>
            MOD <em class="replaceable"><code>M</code></em></code></a>
          </p><p>
            Modulo operation. Returns the remainder of
            <em class="replaceable"><code>N</code></em> divided by
            <em class="replaceable"><code>M</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MOD(234, 10);</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT 253 % 7;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT MOD(29,9);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT 29 MOD 9;</code></strong>
        -&gt; 2
</pre><p>
            This function is safe to use with
            <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> values.
          </p><p>
            <a class="link" href="functions.html#function_mod"><code class="literal">MOD()</code></a> also works on values
            that have a fractional part and returns the exact remainder
            after division:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MOD(34.5,3);</code></strong>
        -&gt; 1.5
</pre><p>
            <a class="link" href="functions.html#function_mod"><code class="literal">MOD(<em class="replaceable"><code>N</code></em>,0)</code></a>
            returns <code class="literal">NULL</code>.
          </p></li><li class="listitem"><a name="function_pi"></a><p>
            <a class="indexterm" name="idm46444331046752"></a>

            <a class="link" href="functions.html#function_pi"><code class="literal">PI()</code></a>
          </p><p>
            Returns the value of π (pi). The default number of
            decimal places displayed is seven, but MySQL uses the full
            double-precision value internally.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT PI();</code></strong>
        -&gt; 3.141593
mysql&gt; <strong class="userinput"><code>SELECT PI()+0.000000000000000000;</code></strong>
        -&gt; 3.141592653589793116
</pre></li><li class="listitem"><a name="function_pow"></a><p>
            <a class="indexterm" name="idm46444331035808"></a>

            <a class="link" href="functions.html#function_pow"><code class="literal">POW(<em class="replaceable"><code>X</code></em>,<em class="replaceable"><code>Y</code></em>)</code></a>
          </p><p>
            Returns the value of <em class="replaceable"><code>X</code></em> raised to
            the power of <em class="replaceable"><code>Y</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT POW(2,2);</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT POW(2,-2);</code></strong>
        -&gt; 0.25
</pre></li><li class="listitem"><a name="function_power"></a><p>
            <a class="indexterm" name="idm46444331023776"></a>

            <a class="link" href="functions.html#function_power"><code class="literal">POWER(<em class="replaceable"><code>X</code></em>,<em class="replaceable"><code>Y</code></em>)</code></a>
          </p><p>
            This is a synonym for <a class="link" href="functions.html#function_pow"><code class="literal">POW()</code></a>.
          </p></li><li class="listitem"><a name="function_radians"></a><p>
            <a class="indexterm" name="idm46444331014960"></a>

            <a class="link" href="functions.html#function_radians"><code class="literal">RADIANS(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the argument <em class="replaceable"><code>X</code></em>, converted
            from degrees to radians. (Note that π radians equals 180
            degrees.)
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT RADIANS(90);</code></strong>
        -&gt; 1.5707963267949
</pre></li><li class="listitem"><a name="function_rand"></a><p>
            <a class="indexterm" name="idm46444331004896"></a>

            <a class="link" href="functions.html#function_rand"><code class="literal">RAND([<em class="replaceable"><code>N</code></em>])</code></a>
          </p><p>
            Returns a random floating-point value
            <em class="replaceable"><code>v</code></em> in the range
            <code class="literal">0</code> &lt;= <em class="replaceable"><code>v</code></em> &lt;
            <code class="literal">1.0</code>. To obtain a random integer
            <em class="replaceable"><code>R</code></em> in the range
            <em class="replaceable"><code>i</code></em> &lt;=
            <em class="replaceable"><code>R</code></em> &lt;
            <em class="replaceable"><code>j</code></em>, use the expression
            <a class="link" href="functions.html#function_floor"><code class="literal">FLOOR(<em class="replaceable"><code>i</code></em>
            + RAND() * (<em class="replaceable"><code>j</code></em></code></a>
            − <code class="literal"><em class="replaceable"><code>i</code></em>))</code>.
            For example, to obtain a random integer in the range the
            range <code class="literal">7</code> &lt;=
            <em class="replaceable"><code>R</code></em> &lt; <code class="literal">12</code>, use
            the following statement:
          </p><pre data-lang="sql" class="programlisting">SELECT FLOOR(7 + (RAND() * 5));</pre><p>
            If an integer argument <em class="replaceable"><code>N</code></em> is
            specified, it is used as the seed value:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                With a constant initializer argument, the seed is
                initialized once when the statement is prepared, prior
                to execution.
              </p></li><li class="listitem"><p>
                With a nonconstant initializer argument (such as a
                column name), the seed is initialized with the value for
                each invocation of
                <a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a>.
</p></li></ul>
</div>
<p>
            One implication of this behavior is that for equal argument
            values,
            <a class="link" href="functions.html#function_rand"><code class="literal">RAND(<em class="replaceable"><code>N</code></em>)</code></a>
            returns the same value each time, and thus produces a
            repeatable sequence of column values. In the following
            example, the sequence of values produced by
            <code class="literal">RAND(3)</code> is the same both places it
            occurs.
          </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>CREATE TABLE t (i INT);</code></strong>
Query OK, 0 rows affected (0.42 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES(1),(2),(3);</code></strong>
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT i, RAND() FROM t;</code></strong>
+------+------------------+
| i    | RAND()           |
+------+------------------+
|    1 | 0.61914388706828 |
|    2 | 0.93845168309142 |
|    3 | 0.83482678498591 |
+------+------------------+
3 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT i, RAND(3) FROM t;</code></strong>
+------+------------------+
| i    | RAND(3)          |
+------+------------------+
|    1 | 0.90576975597606 |
|    2 | 0.37307905813035 |
|    3 | 0.14808605345719 |
+------+------------------+
3 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT i, RAND() FROM t;</code></strong>
+------+------------------+
| i    | RAND()           |
+------+------------------+
|    1 | 0.35877890638893 |
|    2 | 0.28941420772058 |
|    3 | 0.37073435016976 |
+------+------------------+
3 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT i, RAND(3) FROM t;</code></strong>
+------+------------------+
| i    | RAND(3)          |
+------+------------------+
|    1 | 0.90576975597606 |
|    2 | 0.37307905813035 |
|    3 | 0.14808605345719 |
+------+------------------+
3 rows in set (0.01 sec)
</pre><p>
            <a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a> in a
            <code class="literal">WHERE</code> clause is evaluated for every row
            (when selecting from one table) or combination of rows (when
            selecting from a multiple-table join). Thus, for optimizer
            purposes, <a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a> is not a
            constant value and cannot be used for index optimizations.
            For more information, see
            <a class="xref" href="optimization.html#function-optimization" title="8.2.1.20 Function Call Optimization">Section 8.2.1.20, “Function Call Optimization”</a>.
          </p><p>
            Use of a column with <a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a>
            values in an <code class="literal">ORDER BY</code> or <code class="literal">GROUP
            BY</code> clause may yield unexpected results because for
            either clause a <a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a>
            expression can be evaluated multiple times for the same row,
            each time returning a different result. If the goal is to
            retrieve rows in random order, you can use a statement like
            this:
          </p><pre data-lang="sql" class="programlisting">SELECT * FROM <em class="replaceable"><code>tbl_name</code></em> ORDER BY RAND();
</pre><p>
            To select a random sample from a set of rows, combine
            <code class="literal">ORDER BY RAND()</code> with
            <code class="literal">LIMIT</code>:
          </p><pre data-lang="sql" class="programlisting">SELECT * FROM table1, table2 WHERE a=b AND c&lt;d ORDER BY RAND() LIMIT 1000;</pre><p>
            <a class="link" href="functions.html#function_rand"><code class="literal">RAND()</code></a> is not meant to be a
            perfect random generator. It is a fast way to generate
            random numbers on demand that is portable between platforms
            for the same MySQL version.
          </p><p>
            This function is unsafe for statement-based replication. A
            warning is logged if you use this function when
            <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
            <code class="literal">STATEMENT</code>.
          </p></li><li class="listitem"><a name="function_round"></a><p>
            <a class="indexterm" name="idm46444330954720"></a>

            <a class="link" href="functions.html#function_round"><code class="literal">ROUND(<em class="replaceable"><code>X</code></em>)</code></a>,
            <a class="link" href="functions.html#function_round"><code class="literal">ROUND(<em class="replaceable"><code>X</code></em>,<em class="replaceable"><code>D</code></em>)</code></a>
          </p><p>
            Rounds the argument <em class="replaceable"><code>X</code></em> to
            <em class="replaceable"><code>D</code></em> decimal places. The rounding
            algorithm depends on the data type of
            <em class="replaceable"><code>X</code></em>. <em class="replaceable"><code>D</code></em>
            defaults to 0 if not specified. <em class="replaceable"><code>D</code></em>
            can be negative to cause <em class="replaceable"><code>D</code></em> digits
            left of the decimal point of the value
            <em class="replaceable"><code>X</code></em> to become zero. The maximum
            absolute value for <em class="replaceable"><code>D</code></em> is 30; any
            digits in excess of 30 (or -30) are truncated.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ROUND(-1.23);</code></strong>
        -&gt; -1
mysql&gt; <strong class="userinput"><code>SELECT ROUND(-1.58);</code></strong>
        -&gt; -2
mysql&gt; <strong class="userinput"><code>SELECT ROUND(1.58);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT ROUND(1.298, 1);</code></strong>
        -&gt; 1.3
mysql&gt; <strong class="userinput"><code>SELECT ROUND(1.298, 0);</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT ROUND(23.298, -1);</code></strong>
        -&gt; 20
mysql&gt; <strong class="userinput"><code>SELECT ROUND(.12345678901234567890123456789012345, 35);</code></strong>
        -&gt; 0.123456789012345678901234567890
</pre><p>
            The return value has the same type as the first argument
            (assuming that it is integer, double, or decimal). This
            means that for an integer argument, the result is an integer
            (no decimal places):
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ROUND(150.000,2), ROUND(150,2);</code></strong>
+------------------+--------------+
| ROUND(150.000,2) | ROUND(150,2) |
+------------------+--------------+
|           150.00 |          150 |
+------------------+--------------+
</pre><p>
            <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> uses the following
            rules depending on the type of the first argument:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                For exact-value numbers,
                <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> uses the
                <span class="quote">“<span class="quote">round half away from zero</span>”</span> or <span class="quote">“<span class="quote">round
                toward nearest</span>”</span> rule: A value with a fractional
                part of .5 or greater is rounded up to the next integer
                if positive or down to the next integer if negative. (In
                other words, it is rounded away from zero.) A value with
                a fractional part less than .5 is rounded down to the
                next integer if positive or up to the next integer if
                negative.
              </p></li><li class="listitem"><p>
                For approximate-value numbers, the result depends on the
                C library. On many systems, this means that
                <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> uses the
                <span class="quote">“<span class="quote">round to nearest even</span>”</span> rule: A value with
                a fractional part exactly halfway between two integers
                is rounded to the nearest even integer.
</p></li></ul>
</div>
<p>
            The following example shows how rounding differs for exact
            and approximate values:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ROUND(2.5), ROUND(25E-1);</code></strong>
+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
| 3          |            2 |
+------------+--------------+
</pre><p>
            For more information, see <a class="xref" href="functions.html#precision-math" title="12.25 Precision Math">Section 12.25, “Precision Math”</a>.
          </p></li><li class="listitem"><a name="function_sign"></a><p>
            <a class="indexterm" name="idm46444330921120"></a>

            <a class="link" href="functions.html#function_sign"><code class="literal">SIGN(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the sign of the argument as <code class="literal">-1</code>,
            <code class="literal">0</code>, or <code class="literal">1</code>, depending on
            whether <em class="replaceable"><code>X</code></em> is negative, zero, or
            positive.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SIGN(-32);</code></strong>
        -&gt; -1
mysql&gt; <strong class="userinput"><code>SELECT SIGN(0);</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT SIGN(234);</code></strong>
        -&gt; 1
</pre></li><li class="listitem"><a name="function_sin"></a><p>
            <a class="indexterm" name="idm46444330907744"></a>

            <a class="link" href="functions.html#function_sin"><code class="literal">SIN(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the sine of <em class="replaceable"><code>X</code></em>, where
            <em class="replaceable"><code>X</code></em> is given in radians.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SIN(PI());</code></strong>
        -&gt; 1.2246063538224e-16
mysql&gt; <strong class="userinput"><code>SELECT ROUND(SIN(PI()));</code></strong>
        -&gt; 0
</pre></li><li class="listitem"><a name="function_sqrt"></a><p>
            <a class="indexterm" name="idm46444330896704"></a>

            <a class="link" href="functions.html#function_sqrt"><code class="literal">SQRT(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the square root of a nonnegative number
            <em class="replaceable"><code>X</code></em>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SQRT(4);</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT SQRT(20);</code></strong>
        -&gt; 4.4721359549996
mysql&gt; <strong class="userinput"><code>SELECT SQRT(-16);</code></strong>
        -&gt; NULL
</pre></li><li class="listitem"><a name="function_tan"></a><p>
            <a class="indexterm" name="idm46444330885328"></a>

            <a class="link" href="functions.html#function_tan"><code class="literal">TAN(<em class="replaceable"><code>X</code></em>)</code></a>
          </p><p>
            Returns the tangent of <em class="replaceable"><code>X</code></em>, where
            <em class="replaceable"><code>X</code></em> is given in radians.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TAN(PI());</code></strong>
        -&gt; -1.2246063538224e-16
mysql&gt; <strong class="userinput"><code>SELECT TAN(PI()+1);</code></strong>
        -&gt; 1.5574077246549
</pre></li><li class="listitem"><a name="function_truncate"></a><p>
            <a class="indexterm" name="idm46444330874240"></a>

            <a class="link" href="functions.html#function_truncate"><code class="literal">TRUNCATE(<em class="replaceable"><code>X</code></em>,<em class="replaceable"><code>D</code></em>)</code></a>
          </p><p>
            Returns the number <em class="replaceable"><code>X</code></em>, truncated
            to <em class="replaceable"><code>D</code></em> decimal places. If
            <em class="replaceable"><code>D</code></em> is <code class="literal">0</code>, the
            result has no decimal point or fractional part.
            <em class="replaceable"><code>D</code></em> can be negative to cause
            <em class="replaceable"><code>D</code></em> digits left of the decimal
            point of the value <em class="replaceable"><code>X</code></em> to become
            zero.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TRUNCATE(1.223,1);</code></strong>
        -&gt; 1.2
mysql&gt; <strong class="userinput"><code>SELECT TRUNCATE(1.999,1);</code></strong>
        -&gt; 1.9
mysql&gt; <strong class="userinput"><code>SELECT TRUNCATE(1.999,0);</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT TRUNCATE(-1.999,1);</code></strong>
        -&gt; -1.9
mysql&gt; <strong class="userinput"><code>SELECT TRUNCATE(122,-2);</code></strong>
       -&gt; 100
mysql&gt; <strong class="userinput"><code>SELECT TRUNCATE(10.28*100,0);</code></strong>
       -&gt; 1028
</pre><p>
            All numbers are rounded toward zero.
</p></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="date-and-time-functions"></a>12.6 Date and Time Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444330856864"></a><a class="indexterm" name="idm46444330855792"></a><p>
      This section describes the functions that can be used to
      manipulate temporal values. See
      <a class="xref" href="data-types.html#date-and-time-types" title="11.2 Date and Time Data Types">Section 11.2, “Date and Time Data Types”</a>, for a description of the
      range of values each date and time type has and the valid formats
      in which values may be specified.
</p>
<div class="table">
<a name="idm46444330852960"></a><p class="title"><b>Table 12.10 Date and Time Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists date and time functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_adddate"><code class="literal">ADDDATE()</code></a></td>
<td>
      Add time values (intervals) to a date value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_addtime"><code class="literal">ADDTIME()</code></a></td>
<td>
      Add time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_convert-tz"><code class="literal">CONVERT_TZ()</code></a></td>
<td>
      Convert from one time zone to another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_curdate"><code class="literal">CURDATE()</code></a></td>
<td>
      Return the current date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-date"><code class="literal">CURRENT_DATE()</code>, <code class="literal">CURRENT_DATE</code></a></td>
<td>
      Synonyms for CURDATE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-time"><code class="literal">CURRENT_TIME()</code>, <code class="literal">CURRENT_TIME</code></a></td>
<td>
      Synonyms for CURTIME()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-timestamp"><code class="literal">CURRENT_TIMESTAMP()</code>, <code class="literal">CURRENT_TIMESTAMP</code></a></td>
<td>
      Synonyms for NOW()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_curtime"><code class="literal">CURTIME()</code></a></td>
<td>
      Return the current time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date"><code class="literal">DATE()</code></a></td>
<td>
      Extract the date part of a date or datetime expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a></td>
<td>
      Add time values (intervals) to a date value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a></td>
<td>
      Format date as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB()</code></a></td>
<td>
      Subtract a time value (interval) from a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_datediff"><code class="literal">DATEDIFF()</code></a></td>
<td>
      Subtract two dates
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_day"><code class="literal">DAY()</code></a></td>
<td>
      Synonym for DAYOFMONTH()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayname"><code class="literal">DAYNAME()</code></a></td>
<td>
      Return the name of the weekday
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayofmonth"><code class="literal">DAYOFMONTH()</code></a></td>
<td>
      Return the day of the month (0-31)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayofweek"><code class="literal">DAYOFWEEK()</code></a></td>
<td>
      Return the weekday index of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dayofyear"><code class="literal">DAYOFYEAR()</code></a></td>
<td>
      Return the day of the year (1-366)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_extract"><code class="literal">EXTRACT()</code></a></td>
<td>
      Extract part of a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_from-days"><code class="literal">FROM_DAYS()</code></a></td>
<td>
      Convert a day number to a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_from-unixtime"><code class="literal">FROM_UNIXTIME()</code></a></td>
<td>
      Format Unix timestamp as a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT()</code></a></td>
<td>
      Return a date format string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_hour"><code class="literal">HOUR()</code></a></td>
<td>
      Extract the hour
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_last-day"><code class="literal">LAST_DAY</code></a></td>
<td>
      Return the last day of the month for the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_localtime"><code class="literal">LOCALTIME()</code>, <code class="literal">LOCALTIME</code></a></td>
<td>
      Synonym for NOW()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_localtimestamp"><code class="literal">LOCALTIMESTAMP</code>, <code class="literal">LOCALTIMESTAMP()</code></a></td>
<td>
      Synonym for NOW()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_makedate"><code class="literal">MAKEDATE()</code></a></td>
<td>
      Create a date from the year and day of year
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_maketime"><code class="literal">MAKETIME()</code></a></td>
<td>
      Create time from hour, minute, second
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_microsecond"><code class="literal">MICROSECOND()</code></a></td>
<td>
      Return the microseconds from argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_minute"><code class="literal">MINUTE()</code></a></td>
<td>
      Return the minute from the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_month"><code class="literal">MONTH()</code></a></td>
<td>
      Return the month from the date passed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_monthname"><code class="literal">MONTHNAME()</code></a></td>
<td>
      Return the name of the month
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a></td>
<td>
      Return the current date and time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_period-add"><code class="literal">PERIOD_ADD()</code></a></td>
<td>
      Add a period to a year-month
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_period-diff"><code class="literal">PERIOD_DIFF()</code></a></td>
<td>
      Return the number of months between periods
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_quarter"><code class="literal">QUARTER()</code></a></td>
<td>
      Return the quarter from a date argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sec-to-time"><code class="literal">SEC_TO_TIME()</code></a></td>
<td>
      Converts seconds to 'hh:mm:ss' format
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_second"><code class="literal">SECOND()</code></a></td>
<td>
      Return the second (0-59)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE()</code></a></td>
<td>
      Convert a string to a date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_subdate"><code class="literal">SUBDATE()</code></a></td>
<td>
      Synonym for DATE_SUB() when invoked with three arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_subtime"><code class="literal">SUBTIME()</code></a></td>
<td>
      Subtract times
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a></td>
<td>
      Return the time at which the function executes
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_time"><code class="literal">TIME()</code></a></td>
<td>
      Extract the time portion of the expression passed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_time-format"><code class="literal">TIME_FORMAT()</code></a></td>
<td>
      Format as time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_time-to-sec"><code class="literal">TIME_TO_SEC()</code></a></td>
<td>
      Return the argument converted to seconds
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timediff"><code class="literal">TIMEDIFF()</code></a></td>
<td>
      Subtract time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timestamp"><code class="literal">TIMESTAMP()</code></a></td>
<td>
      With a single argument, this function returns the date or datetime
      expression; with two arguments, the sum of the arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timestampadd"><code class="literal">TIMESTAMPADD()</code></a></td>
<td>
      Add an interval to a datetime expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_timestampdiff"><code class="literal">TIMESTAMPDIFF()</code></a></td>
<td>
      Subtract an interval from a datetime expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS()</code></a></td>
<td>
      Return the date argument converted to days
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_to-seconds"><code class="literal">TO_SECONDS()</code></a></td>
<td>
      Return the date or datetime argument converted to seconds since
      Year 0
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a></td>
<td>
      Return a Unix timestamp
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_utc-date"><code class="literal">UTC_DATE()</code></a></td>
<td>
      Return the current UTC date
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_utc-time"><code class="literal">UTC_TIME()</code></a></td>
<td>
      Return the current UTC time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_utc-timestamp"><code class="literal">UTC_TIMESTAMP()</code></a></td>
<td>
      Return the current UTC date and time
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a></td>
<td>
      Return the week number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_weekday"><code class="literal">WEEKDAY()</code></a></td>
<td>
      Return the weekday index
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_weekofyear"><code class="literal">WEEKOFYEAR()</code></a></td>
<td>
      Return the calendar week of the date (1-53)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_year"><code class="literal">YEAR()</code></a></td>
<td>
      Return the year
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_yearweek"><code class="literal">YEARWEEK()</code></a></td>
<td>
      Return the year and week
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      Here is an example that uses date functions. The following query
      selects all rows with a <em class="replaceable"><code>date_col</code></em> value
      from within the last 30 days:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT <em class="replaceable"><code>something</code></em> FROM <em class="replaceable"><code>tbl_name</code></em></code></strong>
    -&gt; <strong class="userinput"><code>WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) &lt;= <em class="replaceable"><code>date_col</code></em>;</code></strong>
</pre><p>
      The query also selects rows with dates that lie in the future.
    </p><p>
      Functions that expect date values usually accept datetime values
      and ignore the time part. Functions that expect time values
      usually accept datetime values and ignore the date part.
    </p><p>
      Functions that return the current date or time each are evaluated
      only once per query at the start of query execution. This means
      that multiple references to a function such as
      <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a> within a single query always
      produce the same result. (For our purposes, a single query also
      includes a call to a stored program (stored routine, trigger, or
      event) and all subprograms called by that program.) This principle
      also applies to <a class="link" href="functions.html#function_curdate"><code class="literal">CURDATE()</code></a>,
      <a class="link" href="functions.html#function_curtime"><code class="literal">CURTIME()</code></a>,
      <a class="link" href="functions.html#function_utc-date"><code class="literal">UTC_DATE()</code></a>,
      <a class="link" href="functions.html#function_utc-time"><code class="literal">UTC_TIME()</code></a>,
      <a class="link" href="functions.html#function_utc-timestamp"><code class="literal">UTC_TIMESTAMP()</code></a>, and to any of
      their synonyms.
    </p><p>
      The <a class="link" href="functions.html#function_current-timestamp"><code class="literal">CURRENT_TIMESTAMP()</code></a>,
      <a class="link" href="functions.html#function_current-time"><code class="literal">CURRENT_TIME()</code></a>,
      <a class="link" href="functions.html#function_current-date"><code class="literal">CURRENT_DATE()</code></a>, and
      <a class="link" href="functions.html#function_from-unixtime"><code class="literal">FROM_UNIXTIME()</code></a> functions return
      values in the current session time zone, which is available as the
      session value of the <a class="link" href="server-administration.html#sysvar_time_zone"><code class="literal">time_zone</code></a>
      system variable. In addition,
      <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> assumes that its
      argument is a datetime value in the session time zone. See
      <a class="xref" href="server-administration.html#time-zone-support" title="5.1.14 MySQL Server Time Zone Support">Section 5.1.14, “MySQL Server Time Zone Support”</a>.
    </p><p>
      Some date functions can be used with <span class="quote">“<span class="quote">zero</span>”</span> dates or
      incomplete dates such as <code class="literal">'2001-11-00'</code>, whereas
      others cannot. Functions that extract parts of dates typically
      work with incomplete dates and thus can return 0 when you might
      otherwise expect a nonzero value. For example:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DAYOFMONTH('2001-11-00'), MONTH('2005-00-00');</code></strong>
        -&gt; 0, 0
</pre><p>
      Other functions expect complete dates and return
      <code class="literal">NULL</code> for incomplete dates. These include
      functions that perform date arithmetic or that map parts of dates
      to names. For example:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('2006-05-00',INTERVAL 1 DAY);</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT DAYNAME('2006-05-00');</code></strong>
        -&gt; NULL
</pre><p>
      Several functions are strict when passed a
      <a class="link" href="functions.html#function_date"><code class="literal">DATE()</code></a> function value as their
      argument and reject incomplete dates with a day part of zero:
      <a class="link" href="functions.html#function_convert-tz"><code class="literal">CONVERT_TZ()</code></a>,
      <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a>,
      <a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB()</code></a>,
      <a class="link" href="functions.html#function_dayofyear"><code class="literal">DAYOFYEAR()</code></a>,
      <a class="link" href="functions.html#function_timestampdiff"><code class="literal">TIMESTAMPDIFF()</code></a>,
      <a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS()</code></a>,
      <a class="link" href="functions.html#function_to-seconds"><code class="literal">TO_SECONDS()</code></a>,
      <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a>,
      <a class="link" href="functions.html#function_weekday"><code class="literal">WEEKDAY()</code></a>,
      <a class="link" href="functions.html#function_weekofyear"><code class="literal">WEEKOFYEAR()</code></a>,
      <a class="link" href="functions.html#function_yearweek"><code class="literal">YEARWEEK()</code></a>.
    </p><p>
      Fractional seconds for <code class="literal">TIME</code>,
      <code class="literal">DATETIME</code>, and <code class="literal">TIMESTAMP</code>
      values are supported, with up to microsecond precision. Functions
      that take temporal arguments accept values with fractional
      seconds. Return values from temporal functions include fractional
      seconds as appropriate.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_adddate"></a><p>
          <a class="indexterm" name="idm46444330598848"></a>

          <a class="link" href="functions.html#function_adddate"><code class="literal">ADDDATE(<em class="replaceable"><code>date</code></em>,INTERVAL
          <em class="replaceable"><code>expr</code></em>
          <em class="replaceable"><code>unit</code></em>)</code></a>,
          <a class="link" href="functions.html#function_adddate"><code class="literal">ADDDATE(<em class="replaceable"><code>expr</code></em>,<em class="replaceable"><code>days</code></em>)</code></a>
        </p><p>
          When invoked with the <code class="literal">INTERVAL</code> form of the
          second argument, <a class="link" href="functions.html#function_adddate"><code class="literal">ADDDATE()</code></a> is a
          synonym for <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a>. The
          related function <a class="link" href="functions.html#function_subdate"><code class="literal">SUBDATE()</code></a> is a
          synonym for <a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB()</code></a>. For
          information on the <code class="literal">INTERVAL</code>
          <em class="replaceable"><code>unit</code></em> argument, see
          <a class="xref" href="language-structure.html#temporal-intervals" title="Temporal Intervals">Temporal Intervals</a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('2008-01-02', INTERVAL 31 DAY);</code></strong>
        -&gt; '2008-02-02'
mysql&gt; <strong class="userinput"><code>SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY);</code></strong>
        -&gt; '2008-02-02'
</pre><p>
          When invoked with the <em class="replaceable"><code>days</code></em> form of
          the second argument, MySQL treats it as an integer number of
          days to be added to <em class="replaceable"><code>expr</code></em>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ADDDATE('2008-01-02', 31);</code></strong>
        -&gt; '2008-02-02'
</pre></li><li class="listitem"><a name="function_addtime"></a><p>
          <a class="indexterm" name="idm46444330574880"></a>

          <a class="link" href="functions.html#function_addtime"><code class="literal">ADDTIME(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_addtime"><code class="literal">ADDTIME()</code></a> adds
          <em class="replaceable"><code>expr2</code></em> to
          <em class="replaceable"><code>expr1</code></em> and returns the result.
          <em class="replaceable"><code>expr1</code></em> is a time or datetime
          expression, and <em class="replaceable"><code>expr2</code></em> is a time
          expression.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002');</code></strong>
        -&gt; '2008-01-02 01:01:01.000001'
mysql&gt; <strong class="userinput"><code>SELECT ADDTIME('01:00:00.999999', '02:00:00.999998');</code></strong>
        -&gt; '03:00:01.999997'
</pre></li><li class="listitem"><a name="function_convert-tz"></a><p>
          <a class="indexterm" name="idm46444330561040"></a>

          <a class="link" href="functions.html#function_convert-tz"><code class="literal">CONVERT_TZ(<em class="replaceable"><code>dt</code></em>,<em class="replaceable"><code>from_tz</code></em>,<em class="replaceable"><code>to_tz</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_convert-tz"><code class="literal">CONVERT_TZ()</code></a> converts a
          datetime value <em class="replaceable"><code>dt</code></em> from the time
          zone given by <em class="replaceable"><code>from_tz</code></em> to the time
          zone given by <em class="replaceable"><code>to_tz</code></em> and returns the
          resulting value. Time zones are specified as described in
          <a class="xref" href="server-administration.html#time-zone-support" title="5.1.14 MySQL Server Time Zone Support">Section 5.1.14, “MySQL Server Time Zone Support”</a>. This function returns
          <code class="literal">NULL</code> if the arguments are invalid.
        </p><p>
          If the value falls out of the supported range of the
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> type when converted
          from <em class="replaceable"><code>from_tz</code></em> to UTC, no conversion
          occurs. The <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> range is
          described in <a class="xref" href="data-types.html#date-and-time-type-syntax" title="11.2.1 Date and Time Data Type Syntax">Section 11.2.1, “Date and Time Data Type Syntax”</a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');</code></strong>
        -&gt; '2004-01-01 13:00:00'
mysql&gt; <strong class="userinput"><code>SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');</code></strong>
        -&gt; '2004-01-01 22:00:00'
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            To use named time zones such as <code class="literal">'MET'</code> or
            <code class="literal">'Europe/Amsterdam'</code>, the time zone tables
            must be properly set up. For instructions, see
            <a class="xref" href="server-administration.html#time-zone-support" title="5.1.14 MySQL Server Time Zone Support">Section 5.1.14, “MySQL Server Time Zone Support”</a>.
</p>
</div>
</li><li class="listitem"><a name="function_curdate"></a><p>
          <a class="indexterm" name="idm46444330538512"></a>

          <a class="link" href="functions.html#function_curdate"><code class="literal">CURDATE()</code></a>
        </p><p>
          Returns the current date as a value in
          <code class="literal">'<em class="replaceable"><code>YYYY-MM-DD</code></em>'</code> or
          <em class="replaceable"><code>YYYYMMDD</code></em> format, depending on
          whether the function is used in string or numeric context.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CURDATE();</code></strong>
        -&gt; '2008-06-13'
mysql&gt; <strong class="userinput"><code>SELECT CURDATE() + 0;</code></strong>
        -&gt; 20080613
</pre></li><li class="listitem"><a name="function_current-date"></a><p>
          <a class="indexterm" name="idm46444330527072"></a>

          <a class="link" href="functions.html#function_current-date"><code class="literal">CURRENT_DATE</code></a>,
          <a class="link" href="functions.html#function_current-date"><code class="literal">CURRENT_DATE()</code></a>
        </p><p>
          <a class="link" href="functions.html#function_current-date"><code class="literal">CURRENT_DATE</code></a> and
          <a class="link" href="functions.html#function_current-date"><code class="literal">CURRENT_DATE()</code></a> are synonyms for
          <a class="link" href="functions.html#function_curdate"><code class="literal">CURDATE()</code></a>.
        </p></li><li class="listitem"><a name="function_current-time"></a><p>
          <a class="indexterm" name="idm46444330515360"></a>

          <a class="link" href="functions.html#function_current-time"><code class="literal">CURRENT_TIME</code></a>,
          <a class="link" href="functions.html#function_current-time"><code class="literal">CURRENT_TIME([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          <a class="link" href="functions.html#function_current-time"><code class="literal">CURRENT_TIME</code></a> and
          <a class="link" href="functions.html#function_current-time"><code class="literal">CURRENT_TIME()</code></a> are synonyms for
          <a class="link" href="functions.html#function_curtime"><code class="literal">CURTIME()</code></a>.
        </p></li><li class="listitem"><a name="function_current-timestamp"></a><p>
          <a class="indexterm" name="idm46444330503184"></a>

          <a class="link" href="functions.html#function_current-timestamp"><code class="literal">CURRENT_TIMESTAMP</code></a>,
          <a class="link" href="functions.html#function_current-timestamp"><code class="literal">CURRENT_TIMESTAMP([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          <a class="link" href="functions.html#function_current-timestamp"><code class="literal">CURRENT_TIMESTAMP</code></a> and
          <a class="link" href="functions.html#function_current-timestamp"><code class="literal">CURRENT_TIMESTAMP()</code></a> are
          synonyms for <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a>.
        </p></li><li class="listitem"><a name="function_curtime"></a><p>
          <a class="indexterm" name="idm46444330491008"></a>

          <a class="link" href="functions.html#function_curtime"><code class="literal">CURTIME([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          Returns the current time as a value in
          <em class="replaceable"><code>'hh:mm:ss'</code></em> or
          <em class="replaceable"><code>hhmmss</code></em> format, depending on whether
          the function is used in string or numeric context. The value
          is expressed in the session time zone.
        </p><p>
          If the <em class="replaceable"><code>fsp</code></em> argument is given to
          specify a fractional seconds precision from 0 to 6, the return
          value includes a fractional seconds part of that many digits.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CURTIME();</code></strong>
        -&gt; '23:50:26'
mysql&gt; <strong class="userinput"><code>SELECT CURTIME() + 0;</code></strong>
        -&gt; 235026.000000
</pre></li><li class="listitem"><a name="function_date"></a><p>
          <a class="indexterm" name="idm46444330478016"></a>

          <a class="link" href="functions.html#function_date"><code class="literal">DATE(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Extracts the date part of the date or datetime expression
          <em class="replaceable"><code>expr</code></em>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATE('2003-12-31 01:02:03');</code></strong>
        -&gt; '2003-12-31'
</pre></li><li class="listitem"><a name="function_datediff"></a><p>
          <a class="indexterm" name="idm46444330468032"></a>

          <a class="link" href="functions.html#function_datediff"><code class="literal">DATEDIFF(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_datediff"><code class="literal">DATEDIFF()</code></a> returns
          <em class="replaceable"><code>expr1</code></em> −
          <em class="replaceable"><code>expr2</code></em> expressed as a value in days
          from one date to the other. <em class="replaceable"><code>expr1</code></em>
          and <em class="replaceable"><code>expr2</code></em> are date or date-and-time
          expressions. Only the date parts of the values are used in the
          calculation.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATEDIFF('2007-12-31 23:59:59','2007-12-30');</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31');</code></strong>
        -&gt; -31
</pre></li><li class="listitem"><a name="function_date-add"></a><p>
          <a class="indexterm" name="idm46444330453408"></a>

          <a class="indexterm" name="idm46444330452336"></a>

          <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD(<em class="replaceable"><code>date</code></em>,INTERVAL
          <em class="replaceable"><code>expr</code></em>
          <em class="replaceable"><code>unit</code></em>)</code></a>,
          <a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB(<em class="replaceable"><code>date</code></em>,INTERVAL
          <em class="replaceable"><code>expr</code></em>
          <em class="replaceable"><code>unit</code></em>)</code></a>
        </p><p>
          These functions perform date arithmetic. The
          <em class="replaceable"><code>date</code></em> argument specifies the
          starting date or datetime value.
          <em class="replaceable"><code>expr</code></em> is an expression specifying
          the interval value to be added or subtracted from the starting
          date. <em class="replaceable"><code>expr</code></em> is evaluated as a
          string; it may start with a <code class="literal">-</code> for negative
          intervals. <em class="replaceable"><code>unit</code></em> is a keyword
          indicating the units in which the expression should be
          interpreted.
        </p><p>
          For more information about temporal interval syntax, including
          a full list of <em class="replaceable"><code>unit</code></em> specifiers, the
          expected form of the <em class="replaceable"><code>expr</code></em> argument
          for each <em class="replaceable"><code>unit</code></em> value, and rules for
          operand interpretation in temporal arithmetic, see
          <a class="xref" href="language-structure.html#temporal-intervals" title="Temporal Intervals">Temporal Intervals</a>.
        </p><p>
          The return value depends on the arguments:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> if the
              <em class="replaceable"><code>date</code></em> argument is a
              <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> value and your
              calculations involve only <code class="literal">YEAR</code>,
              <code class="literal">MONTH</code>, and <code class="literal">DAY</code> parts
              (that is, no time parts).
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> if the first
              argument is a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> (or
              <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a>) value, or if the
              first argument is a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a>
              and the <em class="replaceable"><code>unit</code></em> value uses
              <code class="literal">HOURS</code>, <code class="literal">MINUTES</code>, or
              <code class="literal">SECONDS</code>.
            </p></li><li class="listitem"><p>
              String otherwise.
</p></li></ul>
</div>
<p>
          To ensure that the result is
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>, you can use
          <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> to convert the first
          argument to <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('2018-05-01',INTERVAL 1 DAY);</code></strong>
        -&gt; '2018-05-02'
mysql&gt; <strong class="userinput"><code>SELECT DATE_SUB('2018-05-01',INTERVAL 1 YEAR);</code></strong>
        -&gt; '2017-05-01'
mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('2020-12-31 23:59:59',</code></strong>
    -&gt;                 <strong class="userinput"><code>INTERVAL 1 SECOND);</code></strong>
        -&gt; '2021-01-01 00:00:00'
mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('2018-12-31 23:59:59',</code></strong>
    -&gt;                 <strong class="userinput"><code>INTERVAL 1 DAY);</code></strong>
        -&gt; '2019-01-01 23:59:59'
mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('2100-12-31 23:59:59',</code></strong>
    -&gt;                 <strong class="userinput"><code>INTERVAL '1:1' MINUTE_SECOND);</code></strong>
        -&gt; '2101-01-01 00:01:00'
mysql&gt; <strong class="userinput"><code>SELECT DATE_SUB('2025-01-01 00:00:00',</code></strong>
    -&gt;                 <strong class="userinput"><code>INTERVAL '1 1:1:1' DAY_SECOND);</code></strong>
        -&gt; '2024-12-30 22:58:59'
mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('1900-01-01 00:00:00',</code></strong>
    -&gt;                 <strong class="userinput"><code>INTERVAL '-1 10' DAY_HOUR);</code></strong>
        -&gt; '1899-12-30 14:00:00'
mysql&gt; <strong class="userinput"><code>SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);</code></strong>
        -&gt; '1997-12-02'
mysql&gt; <strong class="userinput"><code>SELECT DATE_ADD('1992-12-31 23:59:59.000002',</code></strong>
    -&gt;            <strong class="userinput"><code>INTERVAL '1.999999' SECOND_MICROSECOND);</code></strong>
        -&gt; '1993-01-01 00:00:01.000001'
</pre></li><li class="listitem"><a name="function_date-format"></a><p>
          <a class="indexterm" name="idm46444330402608"></a>

          <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT(<em class="replaceable"><code>date</code></em>,<em class="replaceable"><code>format</code></em>)</code></a>
        </p><p>
          Formats the <em class="replaceable"><code>date</code></em> value according to
          the <em class="replaceable"><code>format</code></em> string.
        </p><p>
          The specifiers shown in the following table may be used in the
          <em class="replaceable"><code>format</code></em> string. The
          <code class="literal">%</code> character is required before format
          specifier characters. The specifiers apply to other functions
          as well: <a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE()</code></a>,
          <a class="link" href="functions.html#function_time-format"><code class="literal">TIME_FORMAT()</code></a>,
          <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a>.
</p>
<div class="informaltable">
<table summary="Specifier characters for the DATE_FORMAT function that may be used in the format string and provides a description of each specifier character."><col width="20%"><col width="70%"><thead><tr>
              <th scope="col">Specifier</th>
              <th scope="col">Description</th>
            </tr></thead><tbody><tr>
              <td scope="row"><code class="literal">%a</code></td>
              <td>Abbreviated weekday name
                (<code class="literal">Sun</code>..<code class="literal">Sat</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%b</code></td>
              <td>Abbreviated month name (<code class="literal">Jan</code>..<code class="literal">Dec</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%c</code></td>
              <td>Month, numeric (<code class="literal">0</code>..<code class="literal">12</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%D</code></td>
              <td>Day of the month with English suffix (<code class="literal">0th</code>,
                <code class="literal">1st</code>, <code class="literal">2nd</code>,
                <code class="literal">3rd</code>, …)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%d</code></td>
              <td>Day of the month, numeric (<code class="literal">00</code>..<code class="literal">31</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%e</code></td>
              <td>Day of the month, numeric (<code class="literal">0</code>..<code class="literal">31</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%f</code></td>
              <td>Microseconds (<code class="literal">000000</code>..<code class="literal">999999</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%H</code></td>
              <td>Hour (<code class="literal">00</code>..<code class="literal">23</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%h</code></td>
              <td>Hour (<code class="literal">01</code>..<code class="literal">12</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%I</code></td>
              <td>Hour (<code class="literal">01</code>..<code class="literal">12</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%i</code></td>
              <td>Minutes, numeric (<code class="literal">00</code>..<code class="literal">59</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%j</code></td>
              <td>Day of year (<code class="literal">001</code>..<code class="literal">366</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%k</code></td>
              <td>Hour (<code class="literal">0</code>..<code class="literal">23</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%l</code></td>
              <td>Hour (<code class="literal">1</code>..<code class="literal">12</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%M</code></td>
              <td>Month name (<code class="literal">January</code>..<code class="literal">December</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%m</code></td>
              <td>Month, numeric (<code class="literal">00</code>..<code class="literal">12</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%p</code></td>
              <td><code class="literal">AM</code> or <code class="literal">PM</code></td>
            </tr><tr>
              <td scope="row"><code class="literal">%r</code></td>
              <td>Time, 12-hour (<em class="replaceable"><code>hh:mm:ss</code></em> followed by
                <code class="literal">AM</code> or <code class="literal">PM</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%S</code></td>
              <td>Seconds (<code class="literal">00</code>..<code class="literal">59</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%s</code></td>
              <td>Seconds (<code class="literal">00</code>..<code class="literal">59</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%T</code></td>
              <td>Time, 24-hour (<em class="replaceable"><code>hh:mm:ss</code></em>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%U</code></td>
              <td>Week (<code class="literal">00</code>..<code class="literal">53</code>), where Sunday is the
                first day of the week;
                <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> mode 0</td>
            </tr><tr>
              <td scope="row"><code class="literal">%u</code></td>
              <td>Week (<code class="literal">00</code>..<code class="literal">53</code>), where Monday is the
                first day of the week;
                <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> mode 1</td>
            </tr><tr>
              <td scope="row"><code class="literal">%V</code></td>
              <td>Week (<code class="literal">01</code>..<code class="literal">53</code>), where Sunday is the
                first day of the week;
                <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> mode 2; used with
                <code class="literal">%X</code></td>
            </tr><tr>
              <td scope="row"><code class="literal">%v</code></td>
              <td>Week (<code class="literal">01</code>..<code class="literal">53</code>), where Monday is the
                first day of the week;
                <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> mode 3; used with
                <code class="literal">%x</code></td>
            </tr><tr>
              <td scope="row"><code class="literal">%W</code></td>
              <td>Weekday name (<code class="literal">Sunday</code>..<code class="literal">Saturday</code>)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%w</code></td>
              <td>Day of the week
                (<code class="literal">0</code>=Sunday..<code class="literal">6</code>=Saturday)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%X</code></td>
              <td>Year for the week where Sunday is the first day of the week, numeric,
                four digits; used with <code class="literal">%V</code></td>
            </tr><tr>
              <td scope="row"><code class="literal">%x</code></td>
              <td>Year for the week, where Monday is the first day of the week, numeric,
                four digits; used with <code class="literal">%v</code></td>
            </tr><tr>
              <td scope="row"><code class="literal">%Y</code></td>
              <td>Year, numeric, four digits</td>
            </tr><tr>
              <td scope="row"><code class="literal">%y</code></td>
              <td>Year, numeric (two digits)</td>
            </tr><tr>
              <td scope="row"><code class="literal">%%</code></td>
              <td>A literal <code class="literal">%</code> character</td>
            </tr><tr>
              <td scope="row"><code class="literal">%<em class="replaceable"><code>x</code></em></code></td>
              <td><em class="replaceable"><code>x</code></em>, for any
                <span class="quote">“<span class="quote"><em class="replaceable"><code>x</code></em></span>”</span> not listed
                above</td>
</tr></tbody></table>
</div>
<p>
          Ranges for the month and day specifiers begin with zero due to
          the fact that MySQL permits the storing of incomplete dates
          such as <code class="literal">'2014-00-00'</code>.
        </p><p>
          The language used for day and month names and abbreviations is
          controlled by the value of the
          <a class="link" href="server-administration.html#sysvar_lc_time_names"><code class="literal">lc_time_names</code></a> system variable
          (<a class="xref" href="charset.html#locale-support" title="10.16 MySQL Server Locale Support">Section 10.16, “MySQL Server Locale Support”</a>).
        </p><p>
          For the <code class="literal">%U</code>, <code class="literal">%u</code>,
          <code class="literal">%V</code>, and <code class="literal">%v</code> specifiers,
          see the description of the
          <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> function for information
          about the mode values. The mode affects how week numbering
          occurs.
        </p><p>
          <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a> returns a string
          with a character set and collation given by
          <a class="link" href="server-administration.html#sysvar_character_set_connection"><code class="literal">character_set_connection</code></a> and
          <a class="link" href="server-administration.html#sysvar_collation_connection"><code class="literal">collation_connection</code></a> so that
          it can return month and weekday names containing non-ASCII
          characters.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y');</code></strong>
        -&gt; 'Sunday October 2009'
mysql&gt; <strong class="userinput"><code>SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s');</code></strong>
        -&gt; '22:23:00'
mysql&gt; <strong class="userinput"><code>SELECT DATE_FORMAT('1900-10-04 22:23:00',</code></strong>
    -&gt; <strong class="userinput"><code>                '%D %y %a %d %m %b %j');</code></strong>
        -&gt; '4th 00 Thu 04 10 Oct 277'
mysql&gt; <strong class="userinput"><code>SELECT DATE_FORMAT('1997-10-04 22:23:00',</code></strong>
    -&gt; <strong class="userinput"><code>                '%H %k %I %r %T %S %w');</code></strong>
        -&gt; '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql&gt; <strong class="userinput"><code>SELECT DATE_FORMAT('1999-01-01', '%X %V');</code></strong>
        -&gt; '1998 52'
mysql&gt; <strong class="userinput"><code>SELECT DATE_FORMAT('2006-06-00', '%d');</code></strong>
        -&gt; '00'
</pre></li><li class="listitem"><a name="function_date-sub"></a><p>
          <a class="indexterm" name="idm46444330222928"></a>

          <a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB(<em class="replaceable"><code>date</code></em>,INTERVAL
          <em class="replaceable"><code>expr</code></em>
          <em class="replaceable"><code>unit</code></em>)</code></a>
        </p><p>
          See the description for
          <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a>.
        </p></li><li class="listitem"><a name="function_day"></a><p>
          <a class="indexterm" name="idm46444330213616"></a>

          <a class="link" href="functions.html#function_day"><code class="literal">DAY(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_day"><code class="literal">DAY()</code></a> is a synonym for
          <a class="link" href="functions.html#function_dayofmonth"><code class="literal">DAYOFMONTH()</code></a>.
        </p></li><li class="listitem"><a name="function_dayname"></a><p>
          <a class="indexterm" name="idm46444330203952"></a>

          <a class="link" href="functions.html#function_dayname"><code class="literal">DAYNAME(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the name of the weekday for
          <em class="replaceable"><code>date</code></em>. The language used for the
          name is controlled by the value of the
          <a class="link" href="server-administration.html#sysvar_lc_time_names"><code class="literal">lc_time_names</code></a> system variable
          (<a class="xref" href="charset.html#locale-support" title="10.16 MySQL Server Locale Support">Section 10.16, “MySQL Server Locale Support”</a>).
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DAYNAME('2007-02-03');</code></strong>
        -&gt; 'Saturday'
</pre></li><li class="listitem"><a name="function_dayofmonth"></a><p>
          <a class="indexterm" name="idm46444330192064"></a>

          <a class="link" href="functions.html#function_dayofmonth"><code class="literal">DAYOFMONTH(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the day of the month for
          <em class="replaceable"><code>date</code></em>, in the range
          <code class="literal">1</code> to <code class="literal">31</code>, or
          <code class="literal">0</code> for dates such as
          <code class="literal">'0000-00-00'</code> or
          <code class="literal">'2008-00-00'</code> that have a zero day part.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DAYOFMONTH('2007-02-03');</code></strong>
        -&gt; 3
</pre></li><li class="listitem"><a name="function_dayofweek"></a><p>
          <a class="indexterm" name="idm46444330178624"></a>

          <a class="link" href="functions.html#function_dayofweek"><code class="literal">DAYOFWEEK(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the weekday index for <em class="replaceable"><code>date</code></em>
          (<code class="literal">1</code> = Sunday, <code class="literal">2</code> = Monday,
          …, <code class="literal">7</code> = Saturday). These index values
          correspond to the ODBC standard.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DAYOFWEEK('2007-02-03');</code></strong>
        -&gt; 7
</pre></li><li class="listitem"><a name="function_dayofyear"></a><p>
          <a class="indexterm" name="idm46444330166576"></a>

          <a class="link" href="functions.html#function_dayofyear"><code class="literal">DAYOFYEAR(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the day of the year for
          <em class="replaceable"><code>date</code></em>, in the range
          <code class="literal">1</code> to <code class="literal">366</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DAYOFYEAR('2007-02-03');</code></strong>
        -&gt; 34
</pre></li><li class="listitem"><a name="function_extract"></a><p>
          <a class="indexterm" name="idm46444330155296"></a>

          <a class="link" href="functions.html#function_extract"><code class="literal">EXTRACT(<em class="replaceable"><code>unit</code></em>
          FROM <em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          The <a class="link" href="functions.html#function_extract"><code class="literal">EXTRACT()</code></a> function uses the
          same kinds of <em class="replaceable"><code>unit</code></em> specifiers as
          <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a> or
          <a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB()</code></a>, but extracts parts
          from the date rather than performing date arithmetic. For
          information on the <em class="replaceable"><code>unit</code></em> argument,
          see <a class="xref" href="language-structure.html#temporal-intervals" title="Temporal Intervals">Temporal Intervals</a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT EXTRACT(YEAR FROM '2019-07-02');</code></strong>
        -&gt; 2019
mysql&gt; <strong class="userinput"><code>SELECT EXTRACT(YEAR_MONTH FROM '2019-07-02 01:02:03');</code></strong>
        -&gt; 201907
mysql&gt; <strong class="userinput"><code>SELECT EXTRACT(DAY_MINUTE FROM '2019-07-02 01:02:03');</code></strong>
        -&gt; 20102
mysql&gt; <strong class="userinput"><code>SELECT EXTRACT(MICROSECOND</code></strong>
    -&gt;                <strong class="userinput"><code>FROM '2003-01-02 10:30:00.000123');</code></strong>
        -&gt; 123
</pre></li><li class="listitem"><a name="function_from-days"></a><p>
          <a class="indexterm" name="idm46444330136864"></a>

          <a class="link" href="functions.html#function_from-days"><code class="literal">FROM_DAYS(<em class="replaceable"><code>N</code></em>)</code></a>
        </p><p>
          Given a day number <em class="replaceable"><code>N</code></em>, returns a
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> value.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FROM_DAYS(730669);</code></strong>
        -&gt; '2000-07-03'
</pre><p>
          Use <a class="link" href="functions.html#function_from-days"><code class="literal">FROM_DAYS()</code></a> with caution on
          old dates. It is not intended for use with values that precede
          the advent of the Gregorian calendar (1582). See
          <a class="xref" href="functions.html#mysql-calendar" title="12.8 What Calendar Is Used By MySQL?">Section 12.8, “What Calendar Is Used By MySQL?”</a>.
        </p></li><li class="listitem"><a name="function_from-unixtime"></a><p>
          <a class="indexterm" name="idm46444330123168"></a>

          <a class="link" href="functions.html#function_from-unixtime"><code class="literal">FROM_UNIXTIME(<em class="replaceable"><code>unix_timestamp</code></em>[,<em class="replaceable"><code>format</code></em>])</code></a>
        </p><p>
          Returns a representation of the
          <em class="replaceable"><code>unix_timestamp</code></em> argument as a value
          in <code class="literal">'<em class="replaceable"><code>YYYY-MM-DD
          hh:mm:ss</code></em>'</code> or
          <em class="replaceable"><code>YYYYMMDDhhmmss</code></em> format, depending on
          whether the function is used in a string or numeric context.
          <em class="replaceable"><code>unix_timestamp</code></em> is an internal
          timestamp value representing seconds since
          <code class="literal">'1970-01-01 00:00:00'</code> UTC, such as produced
          by the <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a>
          function.
        </p><p>
          The return value is expressed in the session time zone.
          (Clients can set the session time zone as described in
          <a class="xref" href="server-administration.html#time-zone-support" title="5.1.14 MySQL Server Time Zone Support">Section 5.1.14, “MySQL Server Time Zone Support”</a>.) The
          <em class="replaceable"><code>format</code></em> string, if given, is used to
          format the result the same way as described in the entry for
          the <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a> function.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FROM_UNIXTIME(1447430881);</code></strong>
        -&gt; '2015-11-13 10:08:01'
mysql&gt; <strong class="userinput"><code>SELECT FROM_UNIXTIME(1447430881) + 0;</code></strong>
        -&gt; 20151113100801
mysql&gt; <strong class="userinput"><code>SELECT FROM_UNIXTIME(1447430881,</code></strong>
    -&gt;                      <strong class="userinput"><code>'%Y %D %M %h:%i:%s %x');</code></strong>
        -&gt; '2015 13th November 10:08:01 2015'
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            If you use <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a>
            and <a class="link" href="functions.html#function_from-unixtime"><code class="literal">FROM_UNIXTIME()</code></a> to
            convert between values in a non-UTC time zone and Unix
            timestamp values, the conversion is lossy because the
            mapping is not one-to-one in both directions. For details,
            see the description of the
            <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> function.
</p>
</div>
</li><li class="listitem"><a name="function_get-format"></a><p>
          <a class="indexterm" name="idm46444330098416"></a>

          <a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT({DATE|TIME|DATETIME},
          {'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL'})</code></a>
        </p><p>
          Returns a format string. This function is useful in
          combination with the
          <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a> and the
          <a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE()</code></a> functions.
        </p><p>
          The possible values for the first and second arguments result
          in several possible format strings (for the specifiers used,
          see the table in the
          <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a> function
          description). ISO format refers to ISO 9075, not ISO 8601.
</p>
<div class="informaltable">
<table summary="Function calls for the GET_FORMAT function along with results for each function call."><col width="60%"><col width="40%"><thead><tr>
              <th scope="col">Function Call</th>
              <th scope="col">Result</th>
            </tr></thead><tbody><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATE,'USA')</code></a></td>
              <td><code class="literal">'%m.%d.%Y'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATE,'JIS')</code></a></td>
              <td><code class="literal">'%Y-%m-%d'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATE,'ISO')</code></a></td>
              <td><code class="literal">'%Y-%m-%d'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATE,'EUR')</code></a></td>
              <td><code class="literal">'%d.%m.%Y'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATE,'INTERNAL')</code></a></td>
              <td><code class="literal">'%Y%m%d'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATETIME,'USA')</code></a></td>
              <td><code class="literal">'%Y-%m-%d %H.%i.%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATETIME,'JIS')</code></a></td>
              <td><code class="literal">'%Y-%m-%d %H:%i:%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATETIME,'ISO')</code></a></td>
              <td><code class="literal">'%Y-%m-%d %H:%i:%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATETIME,'EUR')</code></a></td>
              <td><code class="literal">'%Y-%m-%d %H.%i.%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(DATETIME,'INTERNAL')</code></a></td>
              <td><code class="literal">'%Y%m%d%H%i%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(TIME,'USA')</code></a></td>
              <td><code class="literal">'%h:%i:%s %p'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(TIME,'JIS')</code></a></td>
              <td><code class="literal">'%H:%i:%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(TIME,'ISO')</code></a></td>
              <td><code class="literal">'%H:%i:%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(TIME,'EUR')</code></a></td>
              <td><code class="literal">'%H.%i.%s'</code></td>
            </tr><tr>
              <td scope="row"><a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT(TIME,'INTERNAL')</code></a></td>
              <td><code class="literal">'%H%i%s'</code></td>
</tr></tbody></table>
</div>
<p>
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> can also be used as
          the first argument to
          <a class="link" href="functions.html#function_get-format"><code class="literal">GET_FORMAT()</code></a>, in which case the
          function returns the same values as for
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR'));</code></strong>
        -&gt; '03.10.2003'
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('10.31.2003',GET_FORMAT(DATE,'USA'));</code></strong>
        -&gt; '2003-10-31'
</pre></li><li class="listitem"><a name="function_hour"></a><p>
          <a class="indexterm" name="idm46444330017488"></a>

          <a class="link" href="functions.html#function_hour"><code class="literal">HOUR(<em class="replaceable"><code>time</code></em>)</code></a>
        </p><p>
          Returns the hour for <em class="replaceable"><code>time</code></em>. The
          range of the return value is <code class="literal">0</code> to
          <code class="literal">23</code> for time-of-day values. However, the
          range of <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a> values actually
          is much larger, so <code class="literal">HOUR</code> can return values
          greater than <code class="literal">23</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HOUR('10:05:03');</code></strong>
        -&gt; 10
mysql&gt; <strong class="userinput"><code>SELECT HOUR('272:59:59');</code></strong>
        -&gt; 272
</pre></li><li class="listitem"><a name="function_last-day"></a><p>
          <a class="indexterm" name="idm46444330002720"></a>

          <a class="link" href="functions.html#function_last-day"><code class="literal">LAST_DAY(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Takes a date or datetime value and returns the corresponding
          value for the last day of the month. Returns
          <code class="literal">NULL</code> if the argument is invalid.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LAST_DAY('2003-02-05');</code></strong>
        -&gt; '2003-02-28'
mysql&gt; <strong class="userinput"><code>SELECT LAST_DAY('2004-02-05');</code></strong>
        -&gt; '2004-02-29'
mysql&gt; <strong class="userinput"><code>SELECT LAST_DAY('2004-01-01 01:01:01');</code></strong>
        -&gt; '2004-01-31'
mysql&gt; <strong class="userinput"><code>SELECT LAST_DAY('2003-03-32');</code></strong>
        -&gt; NULL
</pre></li><li class="listitem"><a name="function_localtime"></a><p>
          <a class="indexterm" name="idm46444329990048"></a>

          <a class="link" href="functions.html#function_localtime"><code class="literal">LOCALTIME</code></a>,
          <a class="link" href="functions.html#function_localtime"><code class="literal">LOCALTIME([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          <a class="link" href="functions.html#function_localtime"><code class="literal">LOCALTIME</code></a> and
          <a class="link" href="functions.html#function_localtime"><code class="literal">LOCALTIME()</code></a> are synonyms for
          <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a>.
        </p></li><li class="listitem"><a name="function_localtimestamp"></a><p>
          <a class="indexterm" name="idm46444329977952"></a>

          <a class="link" href="functions.html#function_localtimestamp"><code class="literal">LOCALTIMESTAMP</code></a>,
          <a class="link" href="functions.html#function_localtimestamp"><code class="literal">LOCALTIMESTAMP([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          <a class="link" href="functions.html#function_localtimestamp"><code class="literal">LOCALTIMESTAMP</code></a> and
          <a class="link" href="functions.html#function_localtimestamp"><code class="literal">LOCALTIMESTAMP()</code></a> are synonyms
          for <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a>.
        </p></li><li class="listitem"><a name="function_makedate"></a><p>
          <a class="indexterm" name="idm46444329965856"></a>

          <a class="link" href="functions.html#function_makedate"><code class="literal">MAKEDATE(<em class="replaceable"><code>year</code></em>,<em class="replaceable"><code>dayofyear</code></em>)</code></a>
        </p><p>
          Returns a date, given year and day-of-year values.
          <em class="replaceable"><code>dayofyear</code></em> must be greater than 0 or
          the result is <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MAKEDATE(2011,31), MAKEDATE(2011,32);</code></strong>
        -&gt; '2011-01-31', '2011-02-01'
mysql&gt; <strong class="userinput"><code>SELECT MAKEDATE(2011,365), MAKEDATE(2014,365);</code></strong>
        -&gt; '2011-12-31', '2014-12-31'
mysql&gt; <strong class="userinput"><code>SELECT MAKEDATE(2011,0);</code></strong>
        -&gt; NULL
</pre></li><li class="listitem"><a name="function_maketime"></a><p>
          <a class="indexterm" name="idm46444329953072"></a>

          <a class="link" href="functions.html#function_maketime"><code class="literal">MAKETIME(<em class="replaceable"><code>hour</code></em>,<em class="replaceable"><code>minute</code></em>,<em class="replaceable"><code>second</code></em>)</code></a>
        </p><p>
          Returns a time value calculated from the
          <em class="replaceable"><code>hour</code></em>,
          <em class="replaceable"><code>minute</code></em>, and
          <em class="replaceable"><code>second</code></em> arguments.
        </p><p>
          The <em class="replaceable"><code>second</code></em> argument can have a
          fractional part.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MAKETIME(12,15,30);</code></strong>
        -&gt; '12:15:30'
</pre></li><li class="listitem"><a name="function_microsecond"></a><p>
          <a class="indexterm" name="idm46444329940528"></a>

          <a class="link" href="functions.html#function_microsecond"><code class="literal">MICROSECOND(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Returns the microseconds from the time or datetime expression
          <em class="replaceable"><code>expr</code></em> as a number in the range from
          <code class="literal">0</code> to <code class="literal">999999</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MICROSECOND('12:00:00.123456');</code></strong>
        -&gt; 123456
mysql&gt; <strong class="userinput"><code>SELECT MICROSECOND('2019-12-31 23:59:59.000010');</code></strong>
        -&gt; 10
</pre></li><li class="listitem"><a name="function_minute"></a><p>
          <a class="indexterm" name="idm46444329928352"></a>

          <a class="link" href="functions.html#function_minute"><code class="literal">MINUTE(<em class="replaceable"><code>time</code></em>)</code></a>
        </p><p>
          Returns the minute for <em class="replaceable"><code>time</code></em>, in the
          range <code class="literal">0</code> to <code class="literal">59</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MINUTE('2008-02-03 10:05:03');</code></strong>
        -&gt; 5
</pre></li><li class="listitem"><a name="function_month"></a><p>
          <a class="indexterm" name="idm46444329917088"></a>

          <a class="link" href="functions.html#function_month"><code class="literal">MONTH(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the month for <em class="replaceable"><code>date</code></em>, in the
          range <code class="literal">1</code> to <code class="literal">12</code> for
          January to December, or <code class="literal">0</code> for dates such as
          <code class="literal">'0000-00-00'</code> or
          <code class="literal">'2008-00-00'</code> that have a zero month part.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MONTH('2008-02-03');</code></strong>
        -&gt; 2
</pre></li><li class="listitem"><a name="function_monthname"></a><p>
          <a class="indexterm" name="idm46444329903648"></a>

          <a class="link" href="functions.html#function_monthname"><code class="literal">MONTHNAME(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the full name of the month for
          <em class="replaceable"><code>date</code></em>. The language used for the
          name is controlled by the value of the
          <a class="link" href="server-administration.html#sysvar_lc_time_names"><code class="literal">lc_time_names</code></a> system variable
          (<a class="xref" href="charset.html#locale-support" title="10.16 MySQL Server Locale Support">Section 10.16, “MySQL Server Locale Support”</a>).
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MONTHNAME('2008-02-03');</code></strong>
        -&gt; 'February'
</pre></li><li class="listitem"><a name="function_now"></a><p>
          <a class="indexterm" name="idm46444329891792"></a>

          <a class="link" href="functions.html#function_now"><code class="literal">NOW([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          Returns the current date and time as a value in
          <code class="literal">'<em class="replaceable"><code>YYYY-MM-DD
          hh:mm:ss</code></em>'</code> or
          <em class="replaceable"><code>YYYYMMDDhhmmss</code></em> format, depending on
          whether the function is used in string or numeric context. The
          value is expressed in the session time zone.
        </p><p>
          If the <em class="replaceable"><code>fsp</code></em> argument is given to
          specify a fractional seconds precision from 0 to 6, the return
          value includes a fractional seconds part of that many digits.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT NOW();</code></strong>
        -&gt; '2007-12-15 23:50:26'
mysql&gt; <strong class="userinput"><code>SELECT NOW() + 0;</code></strong>
        -&gt; 20071215235026.000000
</pre><p>
          <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a> returns a constant time
          that indicates the time at which the statement began to
          execute. (Within a stored function or trigger,
          <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a> returns the time at which
          the function or triggering statement began to execute.) This
          differs from the behavior for
          <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a>, which returns the
          exact time at which it executes.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT NOW(), SLEEP(2), NOW();</code></strong>
+---------------------+----------+---------------------+
| NOW()               | SLEEP(2) | NOW()               |
+---------------------+----------+---------------------+
| 2006-04-12 13:47:36 |        0 | 2006-04-12 13:47:36 |
+---------------------+----------+---------------------+

mysql&gt; <strong class="userinput"><code>SELECT SYSDATE(), SLEEP(2), SYSDATE();</code></strong>
+---------------------+----------+---------------------+
| SYSDATE()           | SLEEP(2) | SYSDATE()           |
+---------------------+----------+---------------------+
| 2006-04-12 13:47:44 |        0 | 2006-04-12 13:47:46 |
+---------------------+----------+---------------------+
</pre><p>
          In addition, the <code class="literal">SET TIMESTAMP</code> statement
          affects the value returned by
          <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a> but not by
          <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a>. This means that
          timestamp settings in the binary log have no effect on
          invocations of <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a>.
          Setting the timestamp to a nonzero value causes each
          subsequent invocation of <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a>
          to return that value. Setting the timestamp to zero cancels
          this effect so that <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a> once
          again returns the current date and time.
        </p><p>
          See the description for
          <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a> for additional
          information about the differences between the two functions.
        </p></li><li class="listitem"><a name="function_period-add"></a><p>
          <a class="indexterm" name="idm46444329861728"></a>

          <a class="link" href="functions.html#function_period-add"><code class="literal">PERIOD_ADD(<em class="replaceable"><code>P</code></em>,<em class="replaceable"><code>N</code></em>)</code></a>
        </p><p>
          Adds <em class="replaceable"><code>N</code></em> months to period
          <em class="replaceable"><code>P</code></em> (in the format
          <em class="replaceable"><code>YYMM</code></em> or
          <em class="replaceable"><code>YYYYMM</code></em>). Returns a value in the
          format <em class="replaceable"><code>YYYYMM</code></em>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The period argument <em class="replaceable"><code>P</code></em> is
            <span class="emphasis"><em>not</em></span> a date value.
</p>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT PERIOD_ADD(200801,2);</code></strong>
        -&gt; 200803
</pre></li><li class="listitem"><a name="function_period-diff"></a><p>
          <a class="indexterm" name="idm46444329848064"></a>

          <a class="link" href="functions.html#function_period-diff"><code class="literal">PERIOD_DIFF(<em class="replaceable"><code>P1</code></em>,<em class="replaceable"><code>P2</code></em>)</code></a>
        </p><p>
          Returns the number of months between periods
          <em class="replaceable"><code>P1</code></em> and
          <em class="replaceable"><code>P2</code></em>. <em class="replaceable"><code>P1</code></em>
          and <em class="replaceable"><code>P2</code></em> should be in the format
          <em class="replaceable"><code>YYMM</code></em> or
          <em class="replaceable"><code>YYYYMM</code></em>. Note that the period
          arguments <em class="replaceable"><code>P1</code></em> and
          <em class="replaceable"><code>P2</code></em> are <span class="emphasis"><em>not</em></span>
          date values.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT PERIOD_DIFF(200802,200703);</code></strong>
        -&gt; 11
</pre></li><li class="listitem"><a name="function_quarter"></a><p>
          <a class="indexterm" name="idm46444329834368"></a>

          <a class="link" href="functions.html#function_quarter"><code class="literal">QUARTER(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the quarter of the year for
          <em class="replaceable"><code>date</code></em>, in the range
          <code class="literal">1</code> to <code class="literal">4</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT QUARTER('2008-04-01');</code></strong>
        -&gt; 2
</pre></li><li class="listitem"><a name="function_second"></a><p>
          <a class="indexterm" name="idm46444329823072"></a>

          <a class="link" href="functions.html#function_second"><code class="literal">SECOND(<em class="replaceable"><code>time</code></em>)</code></a>
        </p><p>
          Returns the second for <em class="replaceable"><code>time</code></em>, in the
          range <code class="literal">0</code> to <code class="literal">59</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SECOND('10:05:03');</code></strong>
        -&gt; 3
</pre></li><li class="listitem"><a name="function_sec-to-time"></a><p>
          <a class="indexterm" name="idm46444329811808"></a>

          <a class="link" href="functions.html#function_sec-to-time"><code class="literal">SEC_TO_TIME(<em class="replaceable"><code>seconds</code></em>)</code></a>
        </p><p>
          Returns the <em class="replaceable"><code>seconds</code></em> argument,
          converted to hours, minutes, and seconds, as a
          <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a> value. The range of the
          result is constrained to that of the
          <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a> data type. A warning
          occurs if the argument corresponds to a value outside that
          range.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SEC_TO_TIME(2378);</code></strong>
        -&gt; '00:39:38'
mysql&gt; <strong class="userinput"><code>SELECT SEC_TO_TIME(2378) + 0;</code></strong>
        -&gt; 3938
</pre></li><li class="listitem"><a name="function_str-to-date"></a><p>
          <a class="indexterm" name="idm46444329798464"></a>

          <a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>format</code></em>)</code></a>
        </p><p>
          This is the inverse of the
          <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a> function. It
          takes a string <em class="replaceable"><code>str</code></em> and a format
          string <em class="replaceable"><code>format</code></em>.
          <a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE()</code></a> returns a
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> value if the format
          string contains both date and time parts, or a
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> or
          <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a> value if the string
          contains only date or time parts. If the date, time, or
          datetime value extracted from <em class="replaceable"><code>str</code></em>
          is illegal, <a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE()</code></a>
          returns <code class="literal">NULL</code> and produces a warning.
        </p><p>
          The server scans <em class="replaceable"><code>str</code></em> attempting to
          match <em class="replaceable"><code>format</code></em> to it. The format
          string can contain literal characters and format specifiers
          beginning with <code class="literal">%</code>. Literal characters in
          <em class="replaceable"><code>format</code></em> must match literally in
          <em class="replaceable"><code>str</code></em>. Format specifiers in
          <em class="replaceable"><code>format</code></em> must match a date or time
          part in <em class="replaceable"><code>str</code></em>. For the specifiers
          that can be used in <em class="replaceable"><code>format</code></em>, see the
          <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a> function
          description.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('01,5,2013','%d,%m,%Y');</code></strong>
        -&gt; '2013-05-01'
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('May 1, 2013','%M %d,%Y');</code></strong>
        -&gt; '2013-05-01'
</pre><p>
          Scanning starts at the beginning of
          <em class="replaceable"><code>str</code></em> and fails if
          <em class="replaceable"><code>format</code></em> is found not to match. Extra
          characters at the end of <em class="replaceable"><code>str</code></em> are
          ignored.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('a09:30:17','a%h:%i:%s');</code></strong>
        -&gt; '09:30:17'
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('a09:30:17','%h:%i:%s');</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('09:30:17a','%h:%i:%s');</code></strong>
        -&gt; '09:30:17'
</pre><p>
          Unspecified date or time parts have a value of 0, so
          incompletely specified values in
          <em class="replaceable"><code>str</code></em> produce a result with some or
          all parts set to 0:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('abc','abc');</code></strong>
        -&gt; '0000-00-00'
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('9','%m');</code></strong>
        -&gt; '0000-09-00'
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('9','%s');</code></strong>
        -&gt; '00:00:09'
</pre><p>
          Range checking on the parts of date values is as described in
          <a class="xref" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types">Section 11.2.2, “The DATE, DATETIME, and TIMESTAMP Types”</a>. This means, for example, that
          <span class="quote">“<span class="quote">zero</span>”</span> dates or dates with part values of 0 are
          permitted unless the SQL mode is set to disallow such values.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y');</code></strong>
        -&gt; '0000-00-00'
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y');</code></strong>
        -&gt; '2004-04-31'
</pre><p>
          If the <a class="link" href="server-administration.html#sqlmode_no_zero_date"><code class="literal">NO_ZERO_DATE</code></a> or
          <a class="link" href="server-administration.html#sqlmode_no_zero_in_date"><code class="literal">NO_ZERO_IN_DATE</code></a> SQL mode is
          enabled, zero dates or part of dates are disallowed. In that
          case, <a class="link" href="functions.html#function_str-to-date"><code class="literal">STR_TO_DATE()</code></a> returns
          <code class="literal">NULL</code> and generates a warning:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET sql_mode = '';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('15:35:00', '%H:%i:%s');</code></strong>
+-------------------------------------+
| STR_TO_DATE('15:35:00', '%H:%i:%s') |
+-------------------------------------+
| 15:35:00                            |
+-------------------------------------+
mysql&gt; <strong class="userinput"><code>SET sql_mode = 'NO_ZERO_IN_DATE';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('15:35:00', '%h:%i:%s');</code></strong>
+-------------------------------------+
| STR_TO_DATE('15:35:00', '%h:%i:%s') |
+-------------------------------------+
| NULL                                |
+-------------------------------------+
mysql&gt; <strong class="userinput"><code>SHOW WARNINGS\G</code></strong>
*************************** 1. row ***************************
  Level: Warning
   Code: 1411
Message: Incorrect datetime value: '15:35:00' for function str_to_date
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            You cannot use format <code class="literal">"%X%V"</code> to convert a
            year-week string to a date because the combination of a year
            and week does not uniquely identify a year and month if the
            week crosses a month boundary. To convert a year-week to a
            date, you should also specify the weekday:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT STR_TO_DATE('200442 Monday', '%X%V %W');</code></strong>
        -&gt; '2004-10-18'
</pre>
</div>
</li><li class="listitem"><a name="function_subdate"></a><p>
          <a class="indexterm" name="idm46444329745376"></a>

          <a class="link" href="functions.html#function_subdate"><code class="literal">SUBDATE(<em class="replaceable"><code>date</code></em>,INTERVAL
          <em class="replaceable"><code>expr</code></em>
          <em class="replaceable"><code>unit</code></em>)</code></a>,
          <a class="link" href="functions.html#function_subdate"><code class="literal">SUBDATE(<em class="replaceable"><code>expr</code></em>,<em class="replaceable"><code>days</code></em>)</code></a>
        </p><p>
          When invoked with the <code class="literal">INTERVAL</code> form of the
          second argument, <a class="link" href="functions.html#function_subdate"><code class="literal">SUBDATE()</code></a> is a
          synonym for <a class="link" href="functions.html#function_date-sub"><code class="literal">DATE_SUB()</code></a>. For
          information on the <code class="literal">INTERVAL</code>
          <em class="replaceable"><code>unit</code></em> argument, see the discussion
          for <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATE_SUB('2008-01-02', INTERVAL 31 DAY);</code></strong>
        -&gt; '2007-12-02'
mysql&gt; <strong class="userinput"><code>SELECT SUBDATE('2008-01-02', INTERVAL 31 DAY);</code></strong>
        -&gt; '2007-12-02'
</pre><p>
          The second form enables the use of an integer value for
          <em class="replaceable"><code>days</code></em>. In such cases, it is
          interpreted as the number of days to be subtracted from the
          date or datetime expression <em class="replaceable"><code>expr</code></em>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SUBDATE('2008-01-02 12:00:00', 31);</code></strong>
        -&gt; '2007-12-02 12:00:00'
</pre></li><li class="listitem"><a name="function_subtime"></a><p>
          <a class="indexterm" name="idm46444329723760"></a>

          <a class="link" href="functions.html#function_subtime"><code class="literal">SUBTIME(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_subtime"><code class="literal">SUBTIME()</code></a> returns
          <em class="replaceable"><code>expr1</code></em> −
          <em class="replaceable"><code>expr2</code></em> expressed as a value in the
          same format as <em class="replaceable"><code>expr1</code></em>.
          <em class="replaceable"><code>expr1</code></em> is a time or datetime
          expression, and <em class="replaceable"><code>expr2</code></em> is a time
          expression.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SUBTIME('2007-12-31 23:59:59.999999','1 1:1:1.000002');</code></strong>
        -&gt; '2007-12-30 22:58:58.999997'
mysql&gt; <strong class="userinput"><code>SELECT SUBTIME('01:00:00.999999', '02:00:00.999998');</code></strong>
        -&gt; '-00:59:59.999999'
</pre></li><li class="listitem"><a name="function_sysdate"></a><p>
          <a class="indexterm" name="idm46444329709440"></a>

          <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          Returns the current date and time as a value in
          <code class="literal">'<em class="replaceable"><code>YYYY-MM-DD
          hh:mm:ss</code></em>'</code> or
          <em class="replaceable"><code>YYYYMMDDhhmmss</code></em> format, depending on
          whether the function is used in string or numeric context.
        </p><p>
          If the <em class="replaceable"><code>fsp</code></em> argument is given to
          specify a fractional seconds precision from 0 to 6, the return
          value includes a fractional seconds part of that many digits.
        </p><p>
          <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a> returns the time at
          which it executes. This differs from the behavior for
          <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a>, which returns a constant
          time that indicates the time at which the statement began to
          execute. (Within a stored function or trigger,
          <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a> returns the time at which
          the function or triggering statement began to execute.)
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT NOW(), SLEEP(2), NOW();</code></strong>
+---------------------+----------+---------------------+
| NOW()               | SLEEP(2) | NOW()               |
+---------------------+----------+---------------------+
| 2006-04-12 13:47:36 |        0 | 2006-04-12 13:47:36 |
+---------------------+----------+---------------------+

mysql&gt; <strong class="userinput"><code>SELECT SYSDATE(), SLEEP(2), SYSDATE();</code></strong>
+---------------------+----------+---------------------+
| SYSDATE()           | SLEEP(2) | SYSDATE()           |
+---------------------+----------+---------------------+
| 2006-04-12 13:47:44 |        0 | 2006-04-12 13:47:46 |
+---------------------+----------+---------------------+
</pre><p>
          In addition, the <code class="literal">SET TIMESTAMP</code> statement
          affects the value returned by
          <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a> but not by
          <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a>. This means that
          timestamp settings in the binary log have no effect on
          invocations of <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a>.
        </p><p>
          Because <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a> can return
          different values even within the same statement, and is not
          affected by <code class="literal">SET TIMESTAMP</code>, it is
          nondeterministic and therefore unsafe for replication if
          statement-based binary logging is used. If that is a problem,
          you can use row-based logging.
        </p><p>
          Alternatively, you can use the
          <a class="link" href="server-administration.html#option_mysqld_sysdate-is-now"><code class="option">--sysdate-is-now</code></a> option to
          cause <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a> to be an alias
          for <a class="link" href="functions.html#function_now"><code class="literal">NOW()</code></a>. This works if the
          option is used on both the master and the slave.
        </p><p>
          The nondeterministic nature of
          <a class="link" href="functions.html#function_sysdate"><code class="literal">SYSDATE()</code></a> also means that
          indexes cannot be used for evaluating expressions that refer
          to it.
        </p></li><li class="listitem"><a name="function_time"></a><p>
          <a class="indexterm" name="idm46444329677824"></a>

          <a class="link" href="functions.html#function_time"><code class="literal">TIME(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Extracts the time part of the time or datetime expression
          <em class="replaceable"><code>expr</code></em> and returns it as a string.
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TIME('2003-12-31 01:02:03');</code></strong>
        -&gt; '01:02:03'
mysql&gt; <strong class="userinput"><code>SELECT TIME('2003-12-31 01:02:03.000123');</code></strong>
        -&gt; '01:02:03.000123'
</pre></li><li class="listitem"><a name="function_timediff"></a><p>
          <a class="indexterm" name="idm46444329664512"></a>

          <a class="link" href="functions.html#function_timediff"><code class="literal">TIMEDIFF(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_timediff"><code class="literal">TIMEDIFF()</code></a> returns
          <em class="replaceable"><code>expr1</code></em> −
          <em class="replaceable"><code>expr2</code></em> expressed as a time value.
          <em class="replaceable"><code>expr1</code></em> and
          <em class="replaceable"><code>expr2</code></em> are time or date-and-time
          expressions, but both must be of the same type.
        </p><p>
          The result returned by <code class="literal">TIMEDIFF()</code> is
          limited to the range allowed for
          <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a> values. Alternatively, you
          can use either of the functions
          <a class="link" href="functions.html#function_timestampdiff"><code class="literal">TIMESTAMPDIFF()</code></a> and
          <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a>, both of which
          return integers.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TIMEDIFF('2000:01:01 00:00:00',</code></strong>
    -&gt;                 <strong class="userinput"><code>'2000:01:01 00:00:00.000001');</code></strong>
        -&gt; '-00:00:00.000001'
mysql&gt; <strong class="userinput"><code>SELECT TIMEDIFF('2008-12-31 23:59:59.000001',</code></strong>
    -&gt; <strong class="userinput"><code>                '2008-12-30 01:01:01.000002');</code></strong>
        -&gt; '46:58:57.999999'
</pre></li><li class="listitem"><a name="function_timestamp"></a><p>
          <a class="indexterm" name="idm46444329643456"></a>

          <a class="link" href="functions.html#function_timestamp"><code class="literal">TIMESTAMP(<em class="replaceable"><code>expr</code></em>)</code></a>,
          <a class="link" href="functions.html#function_timestamp"><code class="literal">TIMESTAMP(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
        </p><p>
          With a single argument, this function returns the date or
          datetime expression <em class="replaceable"><code>expr</code></em> as a
          datetime value. With two arguments, it adds the time
          expression <em class="replaceable"><code>expr2</code></em> to the date or
          datetime expression <em class="replaceable"><code>expr1</code></em> and
          returns the result as a datetime value.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TIMESTAMP('2003-12-31');</code></strong>
        -&gt; '2003-12-31 00:00:00'
mysql&gt; <strong class="userinput"><code>SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');</code></strong>
        -&gt; '2004-01-01 00:00:00'
</pre></li><li class="listitem"><a name="function_timestampadd"></a><p>
          <a class="indexterm" name="idm46444329629488"></a>

          <a class="link" href="functions.html#function_timestampadd"><code class="literal">TIMESTAMPADD(<em class="replaceable"><code>unit</code></em>,<em class="replaceable"><code>interval</code></em>,<em class="replaceable"><code>datetime_expr</code></em>)</code></a>
        </p><p>
          Adds the integer expression
          <em class="replaceable"><code>interval</code></em> to the date or datetime
          expression <em class="replaceable"><code>datetime_expr</code></em>. The unit
          for <em class="replaceable"><code>interval</code></em> is given by the
          <em class="replaceable"><code>unit</code></em> argument, which should be one
          of the following values: <code class="literal">MICROSECOND</code>
          (microseconds), <code class="literal">SECOND</code>,
          <code class="literal">MINUTE</code>, <code class="literal">HOUR</code>,
          <code class="literal">DAY</code>, <code class="literal">WEEK</code>,
          <code class="literal">MONTH</code>, <code class="literal">QUARTER</code>, or
          <code class="literal">YEAR</code>.
        </p><p>
          The <em class="replaceable"><code>unit</code></em> value may be specified
          using one of keywords as shown, or with a prefix of
          <code class="literal">SQL_TSI_</code>. For example,
          <code class="literal">DAY</code> and <code class="literal">SQL_TSI_DAY</code> both
          are legal.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');</code></strong>
        -&gt; '2003-01-02 00:01:00'
mysql&gt; <strong class="userinput"><code>SELECT TIMESTAMPADD(WEEK,1,'2003-01-02');</code></strong>
        -&gt; '2003-01-09'
</pre></li><li class="listitem"><a name="function_timestampdiff"></a><p>
          <a class="indexterm" name="idm46444329606928"></a>

          <a class="link" href="functions.html#function_timestampdiff"><code class="literal">TIMESTAMPDIFF(<em class="replaceable"><code>unit</code></em>,<em class="replaceable"><code>datetime_expr1</code></em>,<em class="replaceable"><code>datetime_expr2</code></em>)</code></a>
        </p><p>
          Returns <em class="replaceable"><code>datetime_expr2</code></em> −
          <em class="replaceable"><code>datetime_expr1</code></em>, where
          <em class="replaceable"><code>datetime_expr1</code></em> and
          <em class="replaceable"><code>datetime_expr2</code></em> are date or datetime
          expressions. One expression may be a date and the other a
          datetime; a date value is treated as a datetime having the
          time part <code class="literal">'00:00:00'</code> where necessary. The
          unit for the result (an integer) is given by the
          <em class="replaceable"><code>unit</code></em> argument. The legal values for
          <em class="replaceable"><code>unit</code></em> are the same as those listed
          in the description of the
          <a class="link" href="functions.html#function_timestampadd"><code class="literal">TIMESTAMPADD()</code></a> function.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');</code></strong>
        -&gt; 3
mysql&gt; <strong class="userinput"><code>SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');</code></strong>
        -&gt; -1
mysql&gt; <strong class="userinput"><code>SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55');</code></strong>
        -&gt; 128885
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The order of the date or datetime arguments for this
            function is the opposite of that used with the
            <a class="link" href="functions.html#function_timestamp"><code class="literal">TIMESTAMP()</code></a> function when
            invoked with 2 arguments.
</p>
</div>
</li><li class="listitem"><a name="function_time-format"></a><p>
          <a class="indexterm" name="idm46444329587952"></a>

          <a class="link" href="functions.html#function_time-format"><code class="literal">TIME_FORMAT(<em class="replaceable"><code>time</code></em>,<em class="replaceable"><code>format</code></em>)</code></a>
        </p><p>
          This is used like the
          <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a> function, but the
          <em class="replaceable"><code>format</code></em> string may contain format
          specifiers only for hours, minutes, seconds, and microseconds.
          Other specifiers produce a <code class="literal">NULL</code> value or
          <code class="literal">0</code>.
        </p><p>
          If the <em class="replaceable"><code>time</code></em> value contains an hour
          part that is greater than <code class="literal">23</code>, the
          <code class="literal">%H</code> and <code class="literal">%k</code> hour format
          specifiers produce a value larger than the usual range of
          <code class="literal">0..23</code>. The other hour format specifiers
          produce the hour value modulo 12.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');</code></strong>
        -&gt; '100 100 04 04 4'
</pre></li><li class="listitem"><a name="function_time-to-sec"></a><p>
          <a class="indexterm" name="idm46444329570944"></a>

          <a class="link" href="functions.html#function_time-to-sec"><code class="literal">TIME_TO_SEC(<em class="replaceable"><code>time</code></em>)</code></a>
        </p><p>
          Returns the <em class="replaceable"><code>time</code></em> argument,
          converted to seconds.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TIME_TO_SEC('22:23:00');</code></strong>
        -&gt; 80580
mysql&gt; <strong class="userinput"><code>SELECT TIME_TO_SEC('00:39:38');</code></strong>
        -&gt; 2378
</pre></li><li class="listitem"><a name="function_to-days"></a><p>
          <a class="indexterm" name="idm46444329560288"></a>

          <a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Given a date <em class="replaceable"><code>date</code></em>, returns a day
          number (the number of days since year 0).
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TO_DAYS(950501);</code></strong>
        -&gt; 728779
mysql&gt; <strong class="userinput"><code>SELECT TO_DAYS('2007-10-07');</code></strong>
        -&gt; 733321
</pre><p>
          <a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS()</code></a> is not intended for
          use with values that precede the advent of the Gregorian
          calendar (1582), because it does not take into account the
          days that were lost when the calendar was changed. For dates
          before 1582 (and possibly a later year in other locales),
          results from this function are not reliable. See
          <a class="xref" href="functions.html#mysql-calendar" title="12.8 What Calendar Is Used By MySQL?">Section 12.8, “What Calendar Is Used By MySQL?”</a>, for details.
        </p><p>
          Remember that MySQL converts two-digit year values in dates to
          four-digit form using the rules in
          <a class="xref" href="data-types.html#date-and-time-types" title="11.2 Date and Time Data Types">Section 11.2, “Date and Time Data Types”</a>. For example,
          <code class="literal">'2008-10-07'</code> and
          <code class="literal">'08-10-07'</code> are seen as identical dates:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TO_DAYS('2008-10-07'), TO_DAYS('08-10-07');</code></strong>
        -&gt; 733687, 733687
</pre><p>
          In MySQL, the zero date is defined as
          <code class="literal">'0000-00-00'</code>, even though this date is
          itself considered invalid. This means that, for
          <code class="literal">'0000-00-00'</code> and
          <code class="literal">'0000-01-01'</code>,
          <a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS()</code></a> returns the values
          shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TO_DAYS('0000-00-00');</code></strong>
+-----------------------+
| to_days('0000-00-00') |
+-----------------------+
|                  NULL |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS;</code></strong>
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1292 | Incorrect datetime value: '0000-00-00' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)


mysql&gt; <strong class="userinput"><code>SELECT TO_DAYS('0000-01-01');</code></strong>
+-----------------------+
| to_days('0000-01-01') |
+-----------------------+
|                     1 |
+-----------------------+
1 row in set (0.00 sec)
</pre><p>
          This is true whether or not the
          <a class="link" href="server-administration.html#sqlmode_allow_invalid_dates"><code class="literal">ALLOW_INVALID_DATES</code></a> SQL
          server mode is enabled.
        </p></li><li class="listitem"><a name="function_to-seconds"></a><p>
          <a class="indexterm" name="idm46444329532496"></a>

          <a class="link" href="functions.html#function_to-seconds"><code class="literal">TO_SECONDS(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Given a date or datetime <em class="replaceable"><code>expr</code></em>,
          returns the number of seconds since the year 0. If
          <em class="replaceable"><code>expr</code></em> is not a valid date or
          datetime value, returns <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TO_SECONDS(950501);</code></strong>
        -&gt; 62966505600
mysql&gt; <strong class="userinput"><code>SELECT TO_SECONDS('2009-11-29');</code></strong>
        -&gt; 63426672000
mysql&gt; <strong class="userinput"><code>SELECT TO_SECONDS('2009-11-29 13:43:32');</code></strong>
        -&gt; 63426721412
mysql&gt; <strong class="userinput"><code>SELECT TO_SECONDS( NOW() );</code></strong>
        -&gt; 63426721458
</pre><p>
          Like <a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS()</code></a>,
          <code class="literal">TO_SECONDS()</code> is not intended for use with
          values that precede the advent of the Gregorian calendar
          (1582), because it does not take into account the days that
          were lost when the calendar was changed. For dates before 1582
          (and possibly a later year in other locales), results from
          this function are not reliable. See
          <a class="xref" href="functions.html#mysql-calendar" title="12.8 What Calendar Is Used By MySQL?">Section 12.8, “What Calendar Is Used By MySQL?”</a>, for details.
        </p><p>
          Like <a class="link" href="functions.html#function_to-days"><code class="literal">TO_DAYS()</code></a>,
          <code class="literal">TO_SECONDS()</code>, converts two-digit year
          values in dates to four-digit form using the rules in
          <a class="xref" href="data-types.html#date-and-time-types" title="11.2 Date and Time Data Types">Section 11.2, “Date and Time Data Types”</a>.
        </p><p>
          In MySQL, the zero date is defined as
          <code class="literal">'0000-00-00'</code>, even though this date is
          itself considered invalid. This means that, for
          <code class="literal">'0000-00-00'</code> and
          <code class="literal">'0000-01-01'</code>,
          <a class="link" href="functions.html#function_to-seconds"><code class="literal">TO_SECONDS()</code></a> returns the values
          shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TO_SECONDS('0000-00-00');</code></strong>
+--------------------------+
| TO_SECONDS('0000-00-00') |
+--------------------------+
|                     NULL |
+--------------------------+
1 row in set, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS;</code></strong>
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1292 | Incorrect datetime value: '0000-00-00' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)


mysql&gt; <strong class="userinput"><code>SELECT TO_SECONDS('0000-01-01');</code></strong>
+--------------------------+
| TO_SECONDS('0000-01-01') |
+--------------------------+
|                    86400 |
+--------------------------+
1 row in set (0.00 sec)
</pre><p>
          This is true whether or not the
          <a class="link" href="server-administration.html#sqlmode_allow_invalid_dates"><code class="literal">ALLOW_INVALID_DATES</code></a> SQL
          server mode is enabled.
        </p></li><li class="listitem"><a name="function_unix-timestamp"></a><p>
          <a class="indexterm" name="idm46444329502336"></a>

          <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP([<em class="replaceable"><code>date</code></em>])</code></a>
        </p><p>
          If <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> is called
          with no <em class="replaceable"><code>date</code></em> argument, it returns a
          Unix timestamp representing seconds since <code class="literal">'1970-01-01
          00:00:00'</code> UTC.
        </p><p>
          If <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> is called
          with a <em class="replaceable"><code>date</code></em> argument, it returns
          the value of the argument as seconds since
          <code class="literal">'1970-01-01 00:00:00'</code> UTC. The server
          interprets <em class="replaceable"><code>date</code></em> as a value in the
          session time zone and converts it to an internal Unix
          timestamp value in UTC. (Clients can set the session time zone
          as described in <a class="xref" href="server-administration.html#time-zone-support" title="5.1.14 MySQL Server Time Zone Support">Section 5.1.14, “MySQL Server Time Zone Support”</a>.) The
          <em class="replaceable"><code>date</code></em> argument may be a
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a>,
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>, or
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> string, or a number
          in <em class="replaceable"><code>YYMMDD</code></em>,
          <em class="replaceable"><code>YYMMDDhhmmss</code></em>,
          <em class="replaceable"><code>YYYYMMDD</code></em>, or
          <em class="replaceable"><code>YYYYMMDDhhmmss</code></em> format. If the
          argument includes a time part, it may optionally include a
          fractional seconds part.
        </p><p>
          The return value is an integer if no argument is given or the
          argument does not include a fractional seconds part, or
          <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> if an argument is given
          that includes a fractional seconds part.
        </p><p>
          When the <em class="replaceable"><code>date</code></em> argument is a
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> column,
          <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> returns the
          internal timestamp value directly, with no implicit
          <span class="quote">“<span class="quote">string-to-Unix-timestamp</span>”</span> conversion.
        </p><p>
          The valid range of argument values is the same as for the
          <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> data type:
          <code class="literal">'1970-01-01 00:00:01.000000'</code> UTC to
          <code class="literal">'2038-01-19 03:14:07.999999'</code> UTC. If you
          pass an out-of-range date to
          <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a>, it returns
          <code class="literal">0</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UNIX_TIMESTAMP();</code></strong>
        -&gt; 1447431666
mysql&gt; <strong class="userinput"><code>SELECT UNIX_TIMESTAMP('2015-11-13 10:20:19');</code></strong>
        -&gt; 1447431619
mysql&gt; <strong class="userinput"><code>SELECT UNIX_TIMESTAMP('2015-11-13 10:20:19.012');</code></strong>
        -&gt; 1447431619.012
</pre><a class="indexterm" name="idm46444329470048"></a><p>
          If you use <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> and
          <a class="link" href="functions.html#function_from-unixtime"><code class="literal">FROM_UNIXTIME()</code></a> to convert
          between values in a non-UTC time zone and Unix timestamp
          values, the conversion is lossy because the mapping is not
          one-to-one in both directions. For example, due to conventions
          for local time zone changes such as Daylight Saving Time
          (DST), it is possible for
          <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> to map two
          values that are distinct in a non-UTC time zone to the same
          Unix timestamp value.
          <a class="link" href="functions.html#function_from-unixtime"><code class="literal">FROM_UNIXTIME()</code></a> will map that
          value back to only one of the original values. Here is an
          example, using values that are distinct in the
          <code class="literal">MET</code> time zone:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET time_zone = 'MET';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT UNIX_TIMESTAMP('2005-03-27 03:00:00');</code></strong>
+---------------------------------------+
| UNIX_TIMESTAMP('2005-03-27 03:00:00') |
+---------------------------------------+
|                            1111885200 |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT UNIX_TIMESTAMP('2005-03-27 02:00:00');</code></strong>
+---------------------------------------+
| UNIX_TIMESTAMP('2005-03-27 02:00:00') |
+---------------------------------------+
|                            1111885200 |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT FROM_UNIXTIME(1111885200);</code></strong>
+---------------------------+
| FROM_UNIXTIME(1111885200) |
+---------------------------+
| 2005-03-27 03:00:00       |
+---------------------------+
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            To use named time zones such as <code class="literal">'MET'</code> or
            <code class="literal">'Europe/Amsterdam'</code>, the time zone tables
            must be properly set up. For instructions, see
            <a class="xref" href="server-administration.html#time-zone-support" title="5.1.14 MySQL Server Time Zone Support">Section 5.1.14, “MySQL Server Time Zone Support”</a>.
</p>
</div>
<p>
          If you want to subtract
          <a class="link" href="functions.html#function_unix-timestamp"><code class="literal">UNIX_TIMESTAMP()</code></a> columns, you
          might want to cast them to signed integers. See
          <a class="xref" href="functions.html#cast-functions" title="12.10 Cast Functions and Operators">Section 12.10, “Cast Functions and Operators”</a>.
        </p></li><li class="listitem"><a name="function_utc-date"></a><p>
          <a class="indexterm" name="idm46444329449648"></a>

          <a class="link" href="functions.html#function_utc-date"><code class="literal">UTC_DATE</code></a>,
          <a class="link" href="functions.html#function_utc-date"><code class="literal">UTC_DATE()</code></a>
        </p><p>
          Returns the current UTC date as a value in
          <code class="literal">'<em class="replaceable"><code>YYYY-MM-DD</code></em>'</code> or
          <em class="replaceable"><code>YYYYMMDD</code></em> format, depending on
          whether the function is used in string or numeric context.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UTC_DATE(), UTC_DATE() + 0;</code></strong>
        -&gt; '2003-08-14', 20030814
</pre></li><li class="listitem"><a name="function_utc-time"></a><p>
          <a class="indexterm" name="idm46444329437664"></a>

          <a class="link" href="functions.html#function_utc-time"><code class="literal">UTC_TIME</code></a>,
          <a class="link" href="functions.html#function_utc-time"><code class="literal">UTC_TIME([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          Returns the current UTC time as a value in
          <em class="replaceable"><code>'hh:mm:ss'</code></em> or
          <em class="replaceable"><code>hhmmss</code></em> format, depending on whether
          the function is used in string or numeric context.
        </p><p>
          If the <em class="replaceable"><code>fsp</code></em> argument is given to
          specify a fractional seconds precision from 0 to 6, the return
          value includes a fractional seconds part of that many digits.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UTC_TIME(), UTC_TIME() + 0;</code></strong>
        -&gt; '18:07:53', 180753.000000
</pre></li><li class="listitem"><a name="function_utc-timestamp"></a><p>
          <a class="indexterm" name="idm46444329424960"></a>

          <a class="link" href="functions.html#function_utc-timestamp"><code class="literal">UTC_TIMESTAMP</code></a>,
          <a class="link" href="functions.html#function_utc-timestamp"><code class="literal">UTC_TIMESTAMP([<em class="replaceable"><code>fsp</code></em>])</code></a>
        </p><p>
          Returns the current UTC date and time as a value in
          <code class="literal">'<em class="replaceable"><code>YYYY-MM-DD
          hh:mm:ss</code></em>'</code> or
          <em class="replaceable"><code>YYYYMMDDhhmmss</code></em> format, depending on
          whether the function is used in string or numeric context.
        </p><p>
          If the <em class="replaceable"><code>fsp</code></em> argument is given to
          specify a fractional seconds precision from 0 to 6, the return
          value includes a fractional seconds part of that many digits.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;</code></strong>
        -&gt; '2003-08-14 18:08:04', 20030814180804.000000
</pre></li><li class="listitem"><a name="function_week"></a><p>
          <a class="indexterm" name="idm46444329411504"></a>

          <a class="link" href="functions.html#function_week"><code class="literal">WEEK(<em class="replaceable"><code>date</code></em>[,<em class="replaceable"><code>mode</code></em>])</code></a>
        </p><p>
          This function returns the week number for
          <em class="replaceable"><code>date</code></em>. The two-argument form of
          <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> enables you to specify
          whether the week starts on Sunday or Monday and whether the
          return value should be in the range from <code class="literal">0</code>
          to <code class="literal">53</code> or from <code class="literal">1</code> to
          <code class="literal">53</code>. If the <em class="replaceable"><code>mode</code></em>
          argument is omitted, the value of the
          <a class="link" href="server-administration.html#sysvar_default_week_format"><code class="literal">default_week_format</code></a> system
          variable is used. See
          <a class="xref" href="server-administration.html#server-system-variables" title="5.1.8 Server System Variables">Section 5.1.8, “Server System Variables”</a>.
        </p><p>
          The following table describes how the
          <em class="replaceable"><code>mode</code></em> argument works.
</p>
<div class="informaltable">
<table summary="Now the mode argument of the WEEK function works. For each mode value, the table lists the first day of the week, the range, and a description of week 1."><col width="10%"><col width="20%"><col width="20%"><col width="50%"><thead><tr>
              <th scope="col">Mode</th>
              <th scope="col">First day of week</th>
              <th scope="col">Range</th>
              <th scope="col">Week 1 is the first week …</th>
            </tr></thead><tbody><tr>
              <td scope="row">0</td>
              <td>Sunday</td>
              <td>0-53</td>
              <td>with a Sunday in this year</td>
            </tr><tr>
              <td scope="row">1</td>
              <td>Monday</td>
              <td>0-53</td>
              <td>with 4 or more days this year</td>
            </tr><tr>
              <td scope="row">2</td>
              <td>Sunday</td>
              <td>1-53</td>
              <td>with a Sunday in this year</td>
            </tr><tr>
              <td scope="row">3</td>
              <td>Monday</td>
              <td>1-53</td>
              <td>with 4 or more days this year</td>
            </tr><tr>
              <td scope="row">4</td>
              <td>Sunday</td>
              <td>0-53</td>
              <td>with 4 or more days this year</td>
            </tr><tr>
              <td scope="row">5</td>
              <td>Monday</td>
              <td>0-53</td>
              <td>with a Monday in this year</td>
            </tr><tr>
              <td scope="row">6</td>
              <td>Sunday</td>
              <td>1-53</td>
              <td>with 4 or more days this year</td>
            </tr><tr>
              <td scope="row">7</td>
              <td>Monday</td>
              <td>1-53</td>
              <td>with a Monday in this year</td>
</tr></tbody></table>
</div>
<p>
          For <em class="replaceable"><code>mode</code></em> values with a meaning of
          <span class="quote">“<span class="quote">with 4 or more days this year,</span>”</span> weeks are
          numbered according to ISO 8601:1988:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If the week containing January 1 has 4 or more days in the
              new year, it is week 1.
            </p></li><li class="listitem"><p>
              Otherwise, it is the last week of the previous year, and
              the next week is week 1.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT WEEK('2008-02-20');</code></strong>
        -&gt; 7
mysql&gt; <strong class="userinput"><code>SELECT WEEK('2008-02-20',0);</code></strong>
        -&gt; 7
mysql&gt; <strong class="userinput"><code>SELECT WEEK('2008-02-20',1);</code></strong>
        -&gt; 8
mysql&gt; <strong class="userinput"><code>SELECT WEEK('2008-12-31',1);</code></strong>
        -&gt; 53
</pre><p>
          If a date falls in the last week of the previous year, MySQL
          returns <code class="literal">0</code> if you do not use
          <code class="literal">2</code>, <code class="literal">3</code>,
          <code class="literal">6</code>, or <code class="literal">7</code> as the optional
          <em class="replaceable"><code>mode</code></em> argument:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);</code></strong>
        -&gt; 2000, 0
</pre><p>
          One might argue that <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a>
          should return <code class="literal">52</code> because the given date
          actually occurs in the 52nd week of 1999.
          <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> returns
          <code class="literal">0</code> instead so that the return value is
          <span class="quote">“<span class="quote">the week number in the given year.</span>”</span> This makes
          use of the <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> function
          reliable when combined with other functions that extract a
          date part from a date.
        </p><p>
          If you prefer a result evaluated with respect to the year that
          contains the first day of the week for the given date, use
          <code class="literal">0</code>, <code class="literal">2</code>,
          <code class="literal">5</code>, or <code class="literal">7</code> as the optional
          <em class="replaceable"><code>mode</code></em> argument.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT WEEK('2000-01-01',2);</code></strong>
        -&gt; 52
</pre><p>
          Alternatively, use the
          <a class="link" href="functions.html#function_yearweek"><code class="literal">YEARWEEK()</code></a> function:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT YEARWEEK('2000-01-01');</code></strong>
        -&gt; 199952
mysql&gt; <strong class="userinput"><code>SELECT MID(YEARWEEK('2000-01-01'),5,2);</code></strong>
        -&gt; '52'
</pre></li><li class="listitem"><a name="function_weekday"></a><p>
          <a class="indexterm" name="idm46444329322960"></a>

          <a class="link" href="functions.html#function_weekday"><code class="literal">WEEKDAY(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the weekday index for <em class="replaceable"><code>date</code></em>
          (<code class="literal">0</code> = Monday, <code class="literal">1</code> =
          Tuesday, … <code class="literal">6</code> = Sunday).
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT WEEKDAY('2008-02-03 22:23:00');</code></strong>
        -&gt; 6
mysql&gt; <strong class="userinput"><code>SELECT WEEKDAY('2007-11-06');</code></strong>
        -&gt; 1
</pre></li><li class="listitem"><a name="function_weekofyear"></a><p>
          <a class="indexterm" name="idm46444329310304"></a>

          <a class="link" href="functions.html#function_weekofyear"><code class="literal">WEEKOFYEAR(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the calendar week of the date as a number in the range
          from <code class="literal">1</code> to <code class="literal">53</code>.
          <a class="link" href="functions.html#function_weekofyear"><code class="literal">WEEKOFYEAR()</code></a> is a compatibility
          function that is equivalent to
          <a class="link" href="functions.html#function_week"><code class="literal">WEEK(<em class="replaceable"><code>date</code></em>,3)</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT WEEKOFYEAR('2008-02-20');</code></strong>
        -&gt; 8
</pre></li><li class="listitem"><a name="function_year"></a><p>
          <a class="indexterm" name="idm46444329296464"></a>

          <a class="link" href="functions.html#function_year"><code class="literal">YEAR(<em class="replaceable"><code>date</code></em>)</code></a>
        </p><p>
          Returns the year for <em class="replaceable"><code>date</code></em>, in the
          range <code class="literal">1000</code> to <code class="literal">9999</code>, or
          <code class="literal">0</code> for the <span class="quote">“<span class="quote">zero</span>”</span> date.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT YEAR('1987-01-01');</code></strong>
        -&gt; 1987
</pre></li><li class="listitem"><a name="function_yearweek"></a><p>
          <a class="indexterm" name="idm46444329284064"></a>

          <a class="link" href="functions.html#function_yearweek"><code class="literal">YEARWEEK(<em class="replaceable"><code>date</code></em>)</code></a>,
          <a class="link" href="functions.html#function_yearweek"><code class="literal">YEARWEEK(<em class="replaceable"><code>date</code></em>,<em class="replaceable"><code>mode</code></em>)</code></a>
        </p><p>
          Returns year and week for a date. The year in the result may
          be different from the year in the date argument for the first
          and the last week of the year.
        </p><p>
          The <em class="replaceable"><code>mode</code></em> argument works exactly
          like the <em class="replaceable"><code>mode</code></em> argument to
          <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a>. For the single-argument
          syntax, a <em class="replaceable"><code>mode</code></em> value of 0 is used.
          Unlike <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a>, the value of
          <a class="link" href="server-administration.html#sysvar_default_week_format"><code class="literal">default_week_format</code></a> does not
          influence <a class="link" href="functions.html#function_yearweek"><code class="literal">YEARWEEK()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT YEARWEEK('1987-01-01');</code></strong>
        -&gt; 198652
</pre><p>
          The week number is different from what the
          <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> function would return
          (<code class="literal">0</code>) for optional arguments
          <code class="literal">0</code> or <code class="literal">1</code>, as
          <a class="link" href="functions.html#function_week"><code class="literal">WEEK()</code></a> then returns the week in
          the context of the given year.
</p></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="string-functions"></a>12.7 String Functions and Operators</h2>

</div>

</div>

</div>

<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#string-comparison-functions">12.7.1 String Comparison Functions and Operators</a></span></dt><dt><span class="section"><a href="functions.html#regexp">12.7.2 Regular Expressions</a></span></dt><dt><span class="section"><a href="functions.html#string-functions-charset">12.7.3 Character Set and Collation of Function Results</a></span></dt></dl>
</div>
<a class="indexterm" name="idm46444329261424"></a><a class="indexterm" name="idm46444329260384"></a><a class="indexterm" name="idm46444329258896"></a><a class="indexterm" name="idm46444329257824"></a>
<div class="table">
<a name="idm46444329256336"></a><p class="title"><b>Table 12.11 String Functions and Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists string functions and operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_ascii"><code class="literal">ASCII()</code></a></td>
<td>
      Return numeric value of left-most character
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bin"><code class="literal">BIN()</code></a></td>
<td>
      Return a string containing binary representation of a number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-length"><code class="literal">BIT_LENGTH()</code></a></td>
<td>
      Return length of argument in bits
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_char"><code class="literal">CHAR()</code></a></td>
<td>
      Return the character for each integer passed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_char-length"><code class="literal">CHAR_LENGTH()</code></a></td>
<td>
      Return number of characters in argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_character-length"><code class="literal">CHARACTER_LENGTH()</code></a></td>
<td>
      Synonym for CHAR_LENGTH()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a></td>
<td>
      Return concatenated string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_concat-ws"><code class="literal">CONCAT_WS()</code></a></td>
<td>
      Return concatenate with separator
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_elt"><code class="literal">ELT()</code></a></td>
<td>
      Return string at index number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_export-set"><code class="literal">EXPORT_SET()</code></a></td>
<td>
      Return a string such that for every bit set in the value bits, you
      get an on string and for every unset bit, you get an off string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_field"><code class="literal">FIELD()</code></a></td>
<td>
      Index (position) of first argument in subsequent arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_find-in-set"><code class="literal">FIND_IN_SET()</code></a></td>
<td>
      Index (position) of first argument within second argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_format"><code class="literal">FORMAT()</code></a></td>
<td>
      Return a number formatted to specified number of decimal places
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_from-base64"><code class="literal">FROM_BASE64()</code></a></td>
<td>
      Decode base64 encoded string and return result
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a></td>
<td>
      Hexadecimal representation of decimal or string value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_insert"><code class="literal">INSERT()</code></a></td>
<td>
      Insert substring at specified position up to specified number of
      characters
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_instr"><code class="literal">INSTR()</code></a></td>
<td>
      Return the index of the first occurrence of substring
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lcase"><code class="literal">LCASE()</code></a></td>
<td>
      Synonym for LOWER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_left"><code class="literal">LEFT()</code></a></td>
<td>
      Return the leftmost number of characters as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_length"><code class="literal">LENGTH()</code></a></td>
<td>
      Return the length of a string in bytes
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a></td>
<td>
      Simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_load-file"><code class="literal">LOAD_FILE()</code></a></td>
<td>
      Load the named file
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_locate"><code class="literal">LOCATE()</code></a></td>
<td>
      Return the position of the first occurrence of substring
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a></td>
<td>
      Return the argument in lowercase
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lpad"><code class="literal">LPAD()</code></a></td>
<td>
      Return the string argument, left-padded with the specified string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ltrim"><code class="literal">LTRIM()</code></a></td>
<td>
      Remove leading spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_make-set"><code class="literal">MAKE_SET()</code></a></td>
<td>
      Return a set of comma-separated strings that have the
      corresponding bit in bits set
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_match"><code class="literal">MATCH</code></a></td>
<td>
      Perform full-text search
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mid"><code class="literal">MID()</code></a></td>
<td>
      Return a substring starting from the specified position
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-like"><code class="literal">NOT LIKE</code></a></td>
<td>
      Negation of simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-regexp"><code class="literal">NOT REGEXP</code></a></td>
<td>
      Negation of REGEXP
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_oct"><code class="literal">OCT()</code></a></td>
<td>
      Return a string containing octal representation of a number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_octet-length"><code class="literal">OCTET_LENGTH()</code></a></td>
<td>
      Synonym for LENGTH()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ord"><code class="literal">ORD()</code></a></td>
<td>
      Return character code for leftmost character of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_position"><code class="literal">POSITION()</code></a></td>
<td>
      Synonym for LOCATE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_quote"><code class="literal">QUOTE()</code></a></td>
<td>
      Escape the argument for use in an SQL statement
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">REGEXP</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-instr"><code class="literal">REGEXP_INSTR()</code></a></td>
<td>
      Starting index of substring matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-replace"><code class="literal">REGEXP_REPLACE()</code></a></td>
<td>
      Replace substrings matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-substr"><code class="literal">REGEXP_SUBSTR()</code></a></td>
<td>
      Return substring matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_repeat"><code class="literal">REPEAT()</code></a></td>
<td>
      Repeat a string the specified number of times
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_replace"><code class="literal">REPLACE()</code></a></td>
<td>
      Replace occurrences of a specified string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_reverse"><code class="literal">REVERSE()</code></a></td>
<td>
      Reverse the characters in a string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_right"><code class="literal">RIGHT()</code></a></td>
<td>
      Return the specified rightmost number of characters
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">RLIKE</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rpad"><code class="literal">RPAD()</code></a></td>
<td>
      Append string the specified number of times
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rtrim"><code class="literal">RTRIM()</code></a></td>
<td>
      Remove trailing spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_soundex"><code class="literal">SOUNDEX()</code></a></td>
<td>
      Return a soundex string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_sounds-like"><code class="literal">SOUNDS LIKE</code></a></td>
<td>
      Compare sounds
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_space"><code class="literal">SPACE()</code></a></td>
<td>
      Return a string of the specified number of spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_strcmp"><code class="literal">STRCMP()</code></a></td>
<td>
      Compare two strings
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR()</code></a></td>
<td>
      Return the substring as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING()</code></a></td>
<td>
      Return the substring as specified
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_substring-index"><code class="literal">SUBSTRING_INDEX()</code></a></td>
<td>
      Return a substring from a string before the specified number of
      occurrences of the delimiter
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_to-base64"><code class="literal">TO_BASE64()</code></a></td>
<td>
      Return the argument converted to a base-64 string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_trim"><code class="literal">TRIM()</code></a></td>
<td>
      Remove leading and trailing spaces
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ucase"><code class="literal">UCASE()</code></a></td>
<td>
      Synonym for UPPER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a></td>
<td>
      Return a string containing hex representation of a number
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a></td>
<td>
      Convert to uppercase
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING()</code></a></td>
<td>
      Return the weight string for a string
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      String-valued functions return <code class="literal">NULL</code> if the
      length of the result would be greater than the value of the
      <a class="link" href="server-administration.html#sysvar_max_allowed_packet"><code class="literal">max_allowed_packet</code></a> system
      variable. See <a class="xref" href="server-administration.html#server-configuration" title="5.1.1 Configuring the Server">Section 5.1.1, “Configuring the Server”</a>.
    </p><p>
      For functions that operate on string positions, the first position
      is numbered 1.
    </p><p>
      For functions that take length arguments, noninteger arguments are
      rounded to the nearest integer.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_ascii"></a><p>
          <a class="indexterm" name="idm46444329044800"></a>

          <a class="link" href="functions.html#function_ascii"><code class="literal">ASCII(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the numeric value of the leftmost character of the
          string <em class="replaceable"><code>str</code></em>. Returns
          <code class="literal">0</code> if <em class="replaceable"><code>str</code></em> is the
          empty string. Returns <code class="literal">NULL</code> if
          <em class="replaceable"><code>str</code></em> is <code class="literal">NULL</code>.
          <a class="link" href="functions.html#function_ascii"><code class="literal">ASCII()</code></a> works for 8-bit
          characters.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ASCII('2');</code></strong>
        -&gt; 50
mysql&gt; <strong class="userinput"><code>SELECT ASCII(2);</code></strong>
        -&gt; 50
mysql&gt; <strong class="userinput"><code>SELECT ASCII('dx');</code></strong>
        -&gt; 100
</pre><p>
          See also the <a class="link" href="functions.html#function_ord"><code class="literal">ORD()</code></a> function.
        </p></li><li class="listitem"><a name="function_bin"></a><p>
          <a class="indexterm" name="idm46444329027584"></a>

          <a class="link" href="functions.html#function_bin"><code class="literal">BIN(<em class="replaceable"><code>N</code></em>)</code></a>
        </p><p>
          Returns a string representation of the binary value of
          <em class="replaceable"><code>N</code></em>, where
          <em class="replaceable"><code>N</code></em> is a longlong
          (<a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>) number. This is
          equivalent to
          <a class="link" href="functions.html#function_conv"><code class="literal">CONV(<em class="replaceable"><code>N</code></em>,10,2)</code></a>.
          Returns <code class="literal">NULL</code> if
          <em class="replaceable"><code>N</code></em> is <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT BIN(12);</code></strong>
        -&gt; '1100'
</pre></li><li class="listitem"><a name="function_bit-length"></a><p>
          <a class="indexterm" name="idm46444329012544"></a>

          <a class="link" href="functions.html#function_bit-length"><code class="literal">BIT_LENGTH(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the length of the string
          <em class="replaceable"><code>str</code></em> in bits.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT BIT_LENGTH('text');</code></strong>
        -&gt; 32
</pre></li><li class="listitem"><a name="function_char"></a><p>
          <a class="indexterm" name="idm46444329002784"></a>

          <a class="link" href="functions.html#function_char"><code class="literal">CHAR(<em class="replaceable"><code>N</code></em>,...
          [USING <em class="replaceable"><code>charset_name</code></em>])</code></a>
        </p><p>
          <a class="link" href="functions.html#function_char"><code class="literal">CHAR()</code></a> interprets each argument
          <em class="replaceable"><code>N</code></em> as an integer and returns a
          string consisting of the characters given by the code values
          of those integers. <code class="literal">NULL</code> values are skipped.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CHAR(77,121,83,81,'76');</code></strong>
        -&gt; 'MySQL'
mysql&gt; <strong class="userinput"><code>SELECT CHAR(77,77.3,'77.3');</code></strong>
        -&gt; 'MMM'
</pre><p>
          <a class="link" href="functions.html#function_char"><code class="literal">CHAR()</code></a> arguments larger than
          255 are converted into multiple result bytes. For example,
          <a class="link" href="functions.html#function_char"><code class="literal">CHAR(256)</code></a> is equivalent to
          <a class="link" href="functions.html#function_char"><code class="literal">CHAR(1,0)</code></a>, and
          <a class="link" href="functions.html#function_char"><code class="literal">CHAR(256*256)</code></a> is equivalent to
          <a class="link" href="functions.html#function_char"><code class="literal">CHAR(1,0,0)</code></a>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(CHAR(1,0)), HEX(CHAR(256));</code></strong>
+----------------+----------------+
| HEX(CHAR(1,0)) | HEX(CHAR(256)) |
+----------------+----------------+
| 0100           | 0100           |
+----------------+----------------+
mysql&gt; <strong class="userinput"><code>SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256));</code></strong>
+------------------+--------------------+
| HEX(CHAR(1,0,0)) | HEX(CHAR(256*256)) |
+------------------+--------------------+
| 010000           | 010000             |
+------------------+--------------------+
</pre><p>
          By default, <a class="link" href="functions.html#function_char"><code class="literal">CHAR()</code></a> returns a
          binary string. To produce a string in a given character set,
          use the optional <code class="literal">USING</code> clause:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CHARSET(CHAR(X'65')), CHARSET(CHAR(X'65' USING utf8));</code></strong>
+----------------------+---------------------------------+
| CHARSET(CHAR(X'65')) | CHARSET(CHAR(X'65' USING utf8)) |
+----------------------+---------------------------------+
| binary               | utf8                            |
+----------------------+---------------------------------+
</pre><p>
          If <code class="literal">USING</code> is given and the result string is
          illegal for the given character set, a warning is issued.
          Also, if strict SQL mode is enabled, the result from
          <a class="link" href="functions.html#function_char"><code class="literal">CHAR()</code></a> becomes
          <code class="literal">NULL</code>.
        </p></li><li class="listitem"><a name="function_char-length"></a><p>
          <a class="indexterm" name="idm46444328971312"></a>

          <a class="link" href="functions.html#function_char-length"><code class="literal">CHAR_LENGTH(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the length of the string
          <em class="replaceable"><code>str</code></em>, measured in characters. A
          multibyte character counts as a single character. This means
          that for a string containing five 2-byte characters,
          <a class="link" href="functions.html#function_length"><code class="literal">LENGTH()</code></a> returns
          <code class="literal">10</code>, whereas
          <a class="link" href="functions.html#function_char-length"><code class="literal">CHAR_LENGTH()</code></a> returns
          <code class="literal">5</code>.
        </p></li><li class="listitem"><a name="function_character-length"></a><p>
          <a class="indexterm" name="idm46444328959600"></a>

          <a class="link" href="functions.html#function_character-length"><code class="literal">CHARACTER_LENGTH(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_character-length"><code class="literal">CHARACTER_LENGTH()</code></a> is a synonym
          for <a class="link" href="functions.html#function_char-length"><code class="literal">CHAR_LENGTH()</code></a>.
        </p></li><li class="listitem"><a name="function_concat"></a><p>
          <a class="indexterm" name="idm46444328950016"></a>

          <a class="indexterm" name="idm46444328948944"></a>

          <a class="indexterm" name="idm46444328947872"></a>

          <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT(<em class="replaceable"><code>str1</code></em>,<em class="replaceable"><code>str2</code></em>,...)</code></a>
        </p><p>
          Returns the string that results from concatenating the
          arguments. May have one or more arguments. If all arguments
          are nonbinary strings, the result is a nonbinary string. If
          the arguments include any binary strings, the result is a
          binary string. A numeric argument is converted to its
          equivalent nonbinary string form.
        </p><p>
          <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a> returns
          <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CONCAT('My', 'S', 'QL');</code></strong>
        -&gt; 'MySQL'
mysql&gt; <strong class="userinput"><code>SELECT CONCAT('My', NULL, 'QL');</code></strong>
        -&gt; NULL
mysql&gt; <strong class="userinput"><code>SELECT CONCAT(14.3);</code></strong>
        -&gt; '14.3'
</pre><p>
          For quoted strings, concatenation can be performed by placing
          the strings next to each other:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'My' 'S' 'QL';</code></strong>
        -&gt; 'MySQL'
</pre></li><li class="listitem"><a name="function_concat-ws"></a><p>
          <a class="indexterm" name="idm46444328930496"></a>

          <a class="link" href="functions.html#function_concat-ws"><code class="literal">CONCAT_WS(<em class="replaceable"><code>separator</code></em>,<em class="replaceable"><code>str1</code></em>,<em class="replaceable"><code>str2</code></em>,...)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_concat-ws"><code class="literal">CONCAT_WS()</code></a> stands for
          Concatenate With Separator and is a special form of
          <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a>. The first argument is
          the separator for the rest of the arguments. The separator is
          added between the strings to be concatenated. The separator
          can be a string, as can the rest of the arguments. If the
          separator is <code class="literal">NULL</code>, the result is
          <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CONCAT_WS(',','First name','Second name','Last Name');</code></strong>
        -&gt; 'First name,Second name,Last Name'
mysql&gt; <strong class="userinput"><code>SELECT CONCAT_WS(',','First name',NULL,'Last Name');</code></strong>
        -&gt; 'First name,Last Name'
</pre><p>
          <a class="link" href="functions.html#function_concat-ws"><code class="literal">CONCAT_WS()</code></a> does not skip empty
          strings. However, it does skip any <code class="literal">NULL</code>
          values after the separator argument.
        </p></li><li class="listitem"><a name="function_elt"></a><p>
          <a class="indexterm" name="idm46444328912608"></a>

          <a class="link" href="functions.html#function_elt"><code class="literal">ELT(<em class="replaceable"><code>N</code></em>,<em class="replaceable"><code>str1</code></em>,<em class="replaceable"><code>str2</code></em>,<em class="replaceable"><code>str3</code></em>,...)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_elt"><code class="literal">ELT()</code></a> returns the
          <em class="replaceable"><code>N</code></em>th element of the list of strings:
          <em class="replaceable"><code>str1</code></em> if
          <em class="replaceable"><code>N</code></em> = <code class="literal">1</code>,
          <em class="replaceable"><code>str2</code></em> if
          <em class="replaceable"><code>N</code></em> = <code class="literal">2</code>, and so
          on. Returns <code class="literal">NULL</code> if
          <em class="replaceable"><code>N</code></em> is less than <code class="literal">1</code>
          or greater than the number of arguments.
          <a class="link" href="functions.html#function_elt"><code class="literal">ELT()</code></a> is the complement of
          <a class="link" href="functions.html#function_field"><code class="literal">FIELD()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ELT(1, 'Aa', 'Bb', 'Cc', 'Dd');</code></strong>
        -&gt; 'Aa'
mysql&gt; <strong class="userinput"><code>SELECT ELT(4, 'Aa', 'Bb', 'Cc', 'Dd');</code></strong>
        -&gt; 'Dd'
</pre></li><li class="listitem"><a name="function_export-set"></a><p>
          <a class="indexterm" name="idm46444328892128"></a>

          <a class="link" href="functions.html#function_export-set"><code class="literal">EXPORT_SET(<em class="replaceable"><code>bits</code></em>,<em class="replaceable"><code>on</code></em>,<em class="replaceable"><code>off</code></em>[,<em class="replaceable"><code>separator</code></em>[,<em class="replaceable"><code>number_of_bits</code></em>]])</code></a>
        </p><p>
          Returns a string such that for every bit set in the value
          <em class="replaceable"><code>bits</code></em>, you get an
          <em class="replaceable"><code>on</code></em> string and for every bit not set
          in the value, you get an <em class="replaceable"><code>off</code></em>
          string. Bits in <em class="replaceable"><code>bits</code></em> are examined
          from right to left (from low-order to high-order bits).
          Strings are added to the result from left to right, separated
          by the <em class="replaceable"><code>separator</code></em> string (the
          default being the comma character <code class="literal">,</code>). The
          number of bits examined is given by
          <em class="replaceable"><code>number_of_bits</code></em>, which has a default
          of 64 if not specified.
          <em class="replaceable"><code>number_of_bits</code></em> is silently clipped
          to 64 if larger than 64. It is treated as an unsigned integer,
          so a value of −1 is effectively the same as 64.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT EXPORT_SET(5,'Y','N',',',4);</code></strong>
        -&gt; 'Y,N,Y,N'
mysql&gt; <strong class="userinput"><code>SELECT EXPORT_SET(6,'1','0',',',10);</code></strong>
        -&gt; '0,1,1,0,0,0,0,0,0,0'
</pre></li><li class="listitem"><a name="function_field"></a><p>
          <a class="indexterm" name="idm46444328875696"></a>

          <a class="link" href="functions.html#function_field"><code class="literal">FIELD(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>str1</code></em>,<em class="replaceable"><code>str2</code></em>,<em class="replaceable"><code>str3</code></em>,...)</code></a>
        </p><p>
          Returns the index (position) of <em class="replaceable"><code>str</code></em>
          in the <em class="replaceable"><code>str1</code></em>,
          <em class="replaceable"><code>str2</code></em>,
          <em class="replaceable"><code>str3</code></em>, <code class="literal">...</code> list.
          Returns <code class="literal">0</code> if <em class="replaceable"><code>str</code></em>
          is not found.
        </p><p>
          If all arguments to <a class="link" href="functions.html#function_field"><code class="literal">FIELD()</code></a> are
          strings, all arguments are compared as strings. If all
          arguments are numbers, they are compared as numbers.
          Otherwise, the arguments are compared as double.
        </p><p>
          If <em class="replaceable"><code>str</code></em> is <code class="literal">NULL</code>,
          the return value is <code class="literal">0</code> because
          <code class="literal">NULL</code> fails equality comparison with any
          value. <a class="link" href="functions.html#function_field"><code class="literal">FIELD()</code></a> is the
          complement of <a class="link" href="functions.html#function_elt"><code class="literal">ELT()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FIELD('Bb', 'Aa', 'Bb', 'Cc', 'Dd', 'Ff');</code></strong>
        -&gt; 2
mysql&gt; <strong class="userinput"><code>SELECT FIELD('Gg', 'Aa', 'Bb', 'Cc', 'Dd', 'Ff');</code></strong>
        -&gt; 0
</pre></li><li class="listitem"><a name="function_find-in-set"></a><p>
          <a class="indexterm" name="idm46444328853344"></a>

          <a class="link" href="functions.html#function_find-in-set"><code class="literal">FIND_IN_SET(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>strlist</code></em>)</code></a>
        </p><p>
          Returns a value in the range of 1 to
          <em class="replaceable"><code>N</code></em> if the string
          <em class="replaceable"><code>str</code></em> is in the string list
          <em class="replaceable"><code>strlist</code></em> consisting of
          <em class="replaceable"><code>N</code></em> substrings. A string list is a
          string composed of substrings separated by
          <code class="literal">,</code> characters. If the first argument is a
          constant string and the second is a column of type
          <a class="link" href="data-types.html#set" title="11.3.6 The SET Type"><code class="literal">SET</code></a>, the
          <a class="link" href="functions.html#function_find-in-set"><code class="literal">FIND_IN_SET()</code></a> function is
          optimized to use bit arithmetic. Returns <code class="literal">0</code>
          if <em class="replaceable"><code>str</code></em> is not in
          <em class="replaceable"><code>strlist</code></em> or if
          <em class="replaceable"><code>strlist</code></em> is the empty string.
          Returns <code class="literal">NULL</code> if either argument is
          <code class="literal">NULL</code>. This function does not work properly
          if the first argument contains a comma (<code class="literal">,</code>)
          character.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FIND_IN_SET('b','a,b,c,d');</code></strong>
        -&gt; 2
</pre></li><li class="listitem"><a name="function_format"></a><p>
          <a class="indexterm" name="idm46444328834176"></a>

          <a class="link" href="functions.html#function_format"><code class="literal">FORMAT(<em class="replaceable"><code>X</code></em>,<em class="replaceable"><code>D</code></em>[,<em class="replaceable"><code>locale</code></em>])</code></a>
        </p><p>
          Formats the number <em class="replaceable"><code>X</code></em> to a format
          like <code class="literal">'#,###,###.##'</code>, rounded to
          <em class="replaceable"><code>D</code></em> decimal places, and returns the
          result as a string. If <em class="replaceable"><code>D</code></em> is
          <code class="literal">0</code>, the result has no decimal point or
          fractional part.
        </p><p>
          The optional third parameter enables a locale to be specified
          to be used for the result number's decimal point, thousands
          separator, and grouping between separators. Permissible locale
          values are the same as the legal values for the
          <a class="link" href="server-administration.html#sysvar_lc_time_names"><code class="literal">lc_time_names</code></a> system variable
          (see <a class="xref" href="charset.html#locale-support" title="10.16 MySQL Server Locale Support">Section 10.16, “MySQL Server Locale Support”</a>). If no locale is
          specified, the default is <code class="literal">'en_US'</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FORMAT(12332.123456, 4);</code></strong>
        -&gt; '12,332.1235'
mysql&gt; <strong class="userinput"><code>SELECT FORMAT(12332.1,4);</code></strong>
        -&gt; '12,332.1000'
mysql&gt; <strong class="userinput"><code>SELECT FORMAT(12332.2,0);</code></strong>
        -&gt; '12,332'
mysql&gt; <strong class="userinput"><code>SELECT FORMAT(12332.2,2,'de_DE');</code></strong>
        -&gt; '12.332,20'
</pre></li><li class="listitem"><a name="function_from-base64"></a><p>
          <a class="indexterm" name="idm46444328815376"></a>

          <a class="link" href="functions.html#function_from-base64"><code class="literal">FROM_BASE64(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Takes a string encoded with the base-64 encoded rules used by
          <a class="link" href="functions.html#function_to-base64"><code class="literal">TO_BASE64()</code></a> and returns the
          decoded result as a binary string. The result is
          <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code> or not a valid base-64 string. See the
          description of <a class="link" href="functions.html#function_to-base64"><code class="literal">TO_BASE64()</code></a> for
          details about the encoding and decoding rules.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc'));</code></strong>
        -&gt; 'JWJj', 'abc'
</pre></li><li class="listitem"><a name="function_hex"></a><p>
          <a class="indexterm" name="idm46444328801760"></a>

          <a class="link" href="functions.html#function_hex"><code class="literal">HEX(<em class="replaceable"><code>str</code></em>)</code></a>,
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX(<em class="replaceable"><code>N</code></em>)</code></a>
        </p><p>
          For a string argument <em class="replaceable"><code>str</code></em>,
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a> returns a hexadecimal
          string representation of <em class="replaceable"><code>str</code></em> where
          each byte of each character in <em class="replaceable"><code>str</code></em>
          is converted to two hexadecimal digits. (Multibyte characters
          therefore become more than two digits.) The inverse of this
          operation is performed by the
          <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a> function.
        </p><p>
          For a numeric argument <em class="replaceable"><code>N</code></em>,
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a> returns a hexadecimal
          string representation of the value of
          <em class="replaceable"><code>N</code></em> treated as a longlong
          (<a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>) number. This is
          equivalent to
          <a class="link" href="functions.html#function_conv"><code class="literal">CONV(<em class="replaceable"><code>N</code></em>,10,16)</code></a>.
          The inverse of this operation is performed by
          <a class="link" href="functions.html#function_conv"><code class="literal">CONV(HEX(<em class="replaceable"><code>N</code></em>),16,10)</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT X'616263', HEX('abc'), UNHEX(HEX('abc'));</code></strong>
        -&gt; 'abc', 616263, 'abc'
mysql&gt; <strong class="userinput"><code>SELECT HEX(255), CONV(HEX(255),16,10);</code></strong>
        -&gt; 'FF', 255
</pre></li><li class="listitem"><a name="function_insert"></a><p>
          <a class="indexterm" name="idm46444328778064"></a>

          <a class="link" href="functions.html#function_insert"><code class="literal">INSERT(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>,<em class="replaceable"><code>len</code></em>,<em class="replaceable"><code>newstr</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em>, with the
          substring beginning at position <em class="replaceable"><code>pos</code></em>
          and <em class="replaceable"><code>len</code></em> characters long replaced by
          the string <em class="replaceable"><code>newstr</code></em>. Returns the
          original string if <em class="replaceable"><code>pos</code></em> is not
          within the length of the string. Replaces the rest of the
          string from position <em class="replaceable"><code>pos</code></em> if
          <em class="replaceable"><code>len</code></em> is not within the length of the
          rest of the string. Returns <code class="literal">NULL</code> if any
          argument is <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT INSERT('Quadratic', 3, 4, 'What');</code></strong>
        -&gt; 'QuWhattic'
mysql&gt; <strong class="userinput"><code>SELECT INSERT('Quadratic', -1, 4, 'What');</code></strong>
        -&gt; 'Quadratic'
mysql&gt; <strong class="userinput"><code>SELECT INSERT('Quadratic', 3, 100, 'What');</code></strong>
        -&gt; 'QuWhat'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_instr"></a><p>
          <a class="indexterm" name="idm46444328760704"></a>

          <a class="link" href="functions.html#function_instr"><code class="literal">INSTR(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>substr</code></em>)</code></a>
        </p><p>
          Returns the position of the first occurrence of substring
          <em class="replaceable"><code>substr</code></em> in string
          <em class="replaceable"><code>str</code></em>. This is the same as the
          two-argument form of <a class="link" href="functions.html#function_locate"><code class="literal">LOCATE()</code></a>,
          except that the order of the arguments is reversed.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT INSTR('foobarbar', 'bar');</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT INSTR('xbar', 'foobar');</code></strong>
        -&gt; 0
</pre><p>
          This function is multibyte safe, and is case-sensitive only if
          at least one argument is a binary string.
        </p></li><li class="listitem"><a name="function_lcase"></a><p>
          <a class="indexterm" name="idm46444328747376"></a>

          <a class="link" href="functions.html#function_lcase"><code class="literal">LCASE(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_lcase"><code class="literal">LCASE()</code></a> is a synonym for
          <a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a>.
        </p><p>
          <code class="literal">LCASE()</code> used in a view is rewritten as
          <code class="literal">LOWER()</code> when storing the view's
          definition. (Bug #12844279)
        </p></li><li class="listitem"><a name="function_left"></a><p>
          <a class="indexterm" name="idm46444328735840"></a>

          <a class="link" href="functions.html#function_left"><code class="literal">LEFT(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>len</code></em>)</code></a>
        </p><p>
          Returns the leftmost <em class="replaceable"><code>len</code></em> characters
          from the string <em class="replaceable"><code>str</code></em>, or
          <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LEFT('foobarbar', 5);</code></strong>
        -&gt; 'fooba'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_length"></a><p>
          <a class="indexterm" name="idm46444328723312"></a>

          <a class="link" href="functions.html#function_length"><code class="literal">LENGTH(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the length of the string
          <em class="replaceable"><code>str</code></em>, measured in bytes. A multibyte
          character counts as multiple bytes. This means that for a
          string containing five 2-byte characters,
          <a class="link" href="functions.html#function_length"><code class="literal">LENGTH()</code></a> returns
          <code class="literal">10</code>, whereas
          <a class="link" href="functions.html#function_char-length"><code class="literal">CHAR_LENGTH()</code></a> returns
          <code class="literal">5</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LENGTH('text');</code></strong>
        -&gt; 4
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The <code class="literal">Length()</code> OpenGIS spatial function is
            named <a class="link" href="functions.html#function_st-length"><code class="literal">ST_Length()</code></a> in MySQL.
</p>
</div>
</li><li class="listitem"><a name="function_load-file"></a><p>
          <a class="indexterm" name="idm46444328706736"></a>

          <a class="indexterm" name="idm46444328705664"></a>

          <a class="link" href="functions.html#function_load-file"><code class="literal">LOAD_FILE(<em class="replaceable"><code>file_name</code></em>)</code></a>
        </p><p>
          Reads the file and returns the file contents as a string. To
          use this function, the file must be located on the server
          host, you must specify the full path name to the file, and you
          must have the <a class="link" href="security.html#priv_file"><code class="literal">FILE</code></a> privilege.
          The file must be readable by the server and its size less than
          <a class="link" href="server-administration.html#sysvar_max_allowed_packet"><code class="literal">max_allowed_packet</code></a> bytes. If
          the <a class="link" href="server-administration.html#sysvar_secure_file_priv"><code class="literal">secure_file_priv</code></a> system
          variable is set to a nonempty directory name, the file to be
          loaded must be located in that directory. (Prior to MySQL
          8.0.17, the file must be readable by all, not just readable by
          the server.)
        </p><p>
          If the file does not exist or cannot be read because one of
          the preceding conditions is not satisfied, the function
          returns <code class="literal">NULL</code>.
        </p><p>
          The <a class="link" href="server-administration.html#sysvar_character_set_filesystem"><code class="literal">character_set_filesystem</code></a>
          system variable controls interpretation of file names that are
          given as literal strings.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE t</code></strong>
          <strong class="userinput"><code>  SET blob_col=LOAD_FILE('/tmp/picture')</code></strong>
          <strong class="userinput"><code>  WHERE id=1;</code></strong>
</pre></li><li class="listitem"><a name="function_locate"></a><p>
          <a class="indexterm" name="idm46444328687600"></a>

          <a class="link" href="functions.html#function_locate"><code class="literal">LOCATE(<em class="replaceable"><code>substr</code></em>,<em class="replaceable"><code>str</code></em>)</code></a>,
          <a class="link" href="functions.html#function_locate"><code class="literal">LOCATE(<em class="replaceable"><code>substr</code></em>,<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>)</code></a>
        </p><p>
          The first syntax returns the position of the first occurrence
          of substring <em class="replaceable"><code>substr</code></em> in string
          <em class="replaceable"><code>str</code></em>. The second syntax returns the
          position of the first occurrence of substring
          <em class="replaceable"><code>substr</code></em> in string
          <em class="replaceable"><code>str</code></em>, starting at position
          <em class="replaceable"><code>pos</code></em>. Returns <code class="literal">0</code>
          if <em class="replaceable"><code>substr</code></em> is not in
          <em class="replaceable"><code>str</code></em>. Returns
          <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LOCATE('bar', 'foobarbar');</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT LOCATE('xbar', 'foobar');</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT LOCATE('bar', 'foobarbar', 5);</code></strong>
        -&gt; 7
</pre><p>
          This function is multibyte safe, and is case-sensitive only if
          at least one argument is a binary string.
        </p></li><li class="listitem"><a name="function_lower"></a><p>
          <a class="indexterm" name="idm46444328668128"></a>

          <a class="link" href="functions.html#function_lower"><code class="literal">LOWER(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em> with all
          characters changed to lowercase according to the current
          character set mapping. The default is
          <code class="literal">utf8mb4</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LOWER('QUADRATICALLY');</code></strong>
        -&gt; 'quadratically'
</pre><p>
          <a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a> (and
          <a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a>) are ineffective when
          applied to binary strings
          (<a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>,
          <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a>). To perform lettercase
          conversion of a binary string, first convert it to a nonbinary
          string using a character set appropriate for the data stored
          in the string:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @str = BINARY 'New York';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT LOWER(@str), LOWER(CONVERT(@str USING utf8mb4));</code></strong>
+-------------+------------------------------------+
| LOWER(@str) | LOWER(CONVERT(@str USING utf8mb4)) |
+-------------+------------------------------------+
| New York    | new york                           |
+-------------+------------------------------------+
</pre><p>
          For collations of Unicode character sets,
          <a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a> and
          <a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a> work according to the
          Unicode Collation Algorithm (UCA) version in the collation
          name, if there is one, and UCA 4.0.0 if no version is
          specified. For example, <code class="literal">utf8mb4_0900_ai_ci</code>
          and <code class="literal">utf8_unicode_520_ci</code> work according to
          UCA 9.0.0 and 5.2.0, respectively, whereas
          <code class="literal">utf8_unicode_ci</code> works according to UCA
          4.0.0. See <a class="xref" href="charset.html#charset-unicode-sets" title="10.10.1 Unicode Character Sets">Section 10.10.1, “Unicode Character Sets”</a>.
        </p><p>
          This function is multibyte safe.
        </p><p>
          <code class="literal">LCASE()</code> used within views is rewritten as
          <code class="literal">LOWER()</code>.
        </p></li><li class="listitem"><a name="function_lpad"></a><p>
          <a class="indexterm" name="idm46444328640160"></a>

          <a class="link" href="functions.html#function_lpad"><code class="literal">LPAD(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>len</code></em>,<em class="replaceable"><code>padstr</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em>, left-padded
          with the string <em class="replaceable"><code>padstr</code></em> to a length
          of <em class="replaceable"><code>len</code></em> characters. If
          <em class="replaceable"><code>str</code></em> is longer than
          <em class="replaceable"><code>len</code></em>, the return value is shortened
          to <em class="replaceable"><code>len</code></em> characters.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LPAD('hi',4,'??');</code></strong>
        -&gt; '??hi'
mysql&gt; <strong class="userinput"><code>SELECT LPAD('hi',1,'??');</code></strong>
        -&gt; 'h'
</pre></li><li class="listitem"><a name="function_ltrim"></a><p>
          <a class="indexterm" name="idm46444328626592"></a>

          <a class="link" href="functions.html#function_ltrim"><code class="literal">LTRIM(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em> with leading
          space characters removed.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LTRIM('  barbar');</code></strong>
        -&gt; 'barbar'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_make-set"></a><p>
          <a class="indexterm" name="idm46444328616288"></a>

          <a class="link" href="functions.html#function_make-set"><code class="literal">MAKE_SET(<em class="replaceable"><code>bits</code></em>,<em class="replaceable"><code>str1</code></em>,<em class="replaceable"><code>str2</code></em>,...)</code></a>
        </p><p>
          Returns a set value (a string containing substrings separated
          by <code class="literal">,</code> characters) consisting of the strings
          that have the corresponding bit in
          <em class="replaceable"><code>bits</code></em> set.
          <em class="replaceable"><code>str1</code></em> corresponds to bit 0,
          <em class="replaceable"><code>str2</code></em> to bit 1, and so on.
          <code class="literal">NULL</code> values in
          <em class="replaceable"><code>str1</code></em>,
          <em class="replaceable"><code>str2</code></em>, <code class="literal">...</code> are
          not appended to the result.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MAKE_SET(1,'a','b','c');</code></strong>
        -&gt; 'a'
mysql&gt; <strong class="userinput"><code>SELECT MAKE_SET(1 | 4,'hello','nice','world');</code></strong>
        -&gt; 'hello,world'
mysql&gt; <strong class="userinput"><code>SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world');</code></strong>
        -&gt; 'hello'
mysql&gt; <strong class="userinput"><code>SELECT MAKE_SET(0,'a','b','c');</code></strong>
        -&gt; ''
</pre></li><li class="listitem"><a name="function_mid"></a><p>
          <a class="indexterm" name="idm46444328599168"></a>

          <a class="link" href="functions.html#function_mid"><code class="literal">MID(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>,<em class="replaceable"><code>len</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_mid"><code class="literal">MID(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>,<em class="replaceable"><code>len</code></em>)</code></a>
          is a synonym for
          <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>,<em class="replaceable"><code>len</code></em>)</code></a>.
        </p></li><li class="listitem"><a name="function_oct"></a><p>
          <a class="indexterm" name="idm46444328586448"></a>

          <a class="link" href="functions.html#function_oct"><code class="literal">OCT(<em class="replaceable"><code>N</code></em>)</code></a>
        </p><p>
          Returns a string representation of the octal value of
          <em class="replaceable"><code>N</code></em>, where
          <em class="replaceable"><code>N</code></em> is a longlong
          (<a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>) number. This is
          equivalent to
          <a class="link" href="functions.html#function_conv"><code class="literal">CONV(<em class="replaceable"><code>N</code></em>,10,8)</code></a>.
          Returns <code class="literal">NULL</code> if
          <em class="replaceable"><code>N</code></em> is <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT OCT(12);</code></strong>
        -&gt; '14'
</pre></li><li class="listitem"><a name="function_octet-length"></a><p>
          <a class="indexterm" name="idm46444328571408"></a>

          <a class="link" href="functions.html#function_octet-length"><code class="literal">OCTET_LENGTH(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_octet-length"><code class="literal">OCTET_LENGTH()</code></a> is a synonym for
          <a class="link" href="functions.html#function_length"><code class="literal">LENGTH()</code></a>.
        </p></li><li class="listitem"><a name="function_ord"></a><p>
          <a class="indexterm" name="idm46444328561760"></a>

          <a class="link" href="functions.html#function_ord"><code class="literal">ORD(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          If the leftmost character of the string
          <em class="replaceable"><code>str</code></em> is a multibyte character,
          returns the code for that character, calculated from the
          numeric values of its constituent bytes using this formula:
        </p><pre data-lang="clike" class="programlisting">  (1st byte code)
+ (2nd byte code * 256)
+ (3rd byte code * 256^2) ...</pre><p>
          If the leftmost character is not a multibyte character,
          <a class="link" href="functions.html#function_ord"><code class="literal">ORD()</code></a> returns the same value as
          the <a class="link" href="functions.html#function_ascii"><code class="literal">ASCII()</code></a> function.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ORD('2');</code></strong>
        -&gt; 50
</pre></li><li class="listitem"><a name="function_position"></a><p>
          <a class="indexterm" name="idm46444328547792"></a>

          <a class="link" href="functions.html#function_position"><code class="literal">POSITION(<em class="replaceable"><code>substr</code></em>
          IN <em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_position"><code class="literal">POSITION(<em class="replaceable"><code>substr</code></em>
          IN <em class="replaceable"><code>str</code></em>)</code></a> is a synonym for
          <a class="link" href="functions.html#function_locate"><code class="literal">LOCATE(<em class="replaceable"><code>substr</code></em>,<em class="replaceable"><code>str</code></em>)</code></a>.
        </p></li><li class="listitem"><a name="function_quote"></a><p>
          <a class="indexterm" name="idm46444328536080"></a>

          <a class="link" href="functions.html#function_quote"><code class="literal">QUOTE(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Quotes a string to produce a result that can be used as a
          properly escaped data value in an SQL statement. The string is
          returned enclosed by single quotation marks and with each
          instance of backslash (<code class="literal">\</code>), single quote
          (<code class="literal">'</code>), ASCII <code class="literal">NUL</code>, and
          Control+Z preceded by a backslash. If the argument is
          <code class="literal">NULL</code>, the return value is the word
          <span class="quote">“<span class="quote">NULL</span>”</span> without enclosing single quotation marks.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT QUOTE('Don\'t!');</code></strong>
        -&gt; 'Don\'t!'
mysql&gt; <strong class="userinput"><code>SELECT QUOTE(NULL);</code></strong>
        -&gt; NULL
</pre><a class="indexterm" name="idm46444328524720"></a><p>
          For comparison, see the quoting rules for literal strings and
          within the C API in <a class="xref" href="language-structure.html#string-literals" title="9.1.1 String Literals">Section 9.1.1, “String Literals”</a>, and
          <a class="xref" href="connectors-apis.html#mysql-real-escape-string-quote" title="28.7.6.56 mysql_real_escape_string_quote()">Section 28.7.6.56, “mysql_real_escape_string_quote()”</a>.
        </p></li><li class="listitem"><a name="function_repeat"></a><p>
          <a class="indexterm" name="idm46444328519312"></a>

          <a class="link" href="functions.html#function_repeat"><code class="literal">REPEAT(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>count</code></em>)</code></a>
        </p><p>
          Returns a string consisting of the string
          <em class="replaceable"><code>str</code></em> repeated
          <em class="replaceable"><code>count</code></em> times. If
          <em class="replaceable"><code>count</code></em> is less than 1, returns an
          empty string. Returns <code class="literal">NULL</code> if
          <em class="replaceable"><code>str</code></em> or
          <em class="replaceable"><code>count</code></em> are <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REPEAT('MySQL', 3);</code></strong>
        -&gt; 'MySQLMySQLMySQL'
</pre></li><li class="listitem"><a name="function_replace"></a><p>
          <a class="indexterm" name="idm46444328505856"></a>

          <a class="link" href="functions.html#function_replace"><code class="literal">REPLACE(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>from_str</code></em>,<em class="replaceable"><code>to_str</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em> with all
          occurrences of the string <em class="replaceable"><code>from_str</code></em>
          replaced by the string <em class="replaceable"><code>to_str</code></em>.
          <a class="link" href="functions.html#function_replace"><code class="literal">REPLACE()</code></a> performs a
          case-sensitive match when searching for
          <em class="replaceable"><code>from_str</code></em>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REPLACE('www.mysql.com', 'w', 'Ww');</code></strong>
        -&gt; 'WwWwWw.mysql.com'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_reverse"></a><p>
          <a class="indexterm" name="idm46444328492000"></a>

          <a class="link" href="functions.html#function_reverse"><code class="literal">REVERSE(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em> with the
          order of the characters reversed.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REVERSE('abc');</code></strong>
        -&gt; 'cba'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_right"></a><p>
          <a class="indexterm" name="idm46444328481712"></a>

          <a class="link" href="functions.html#function_right"><code class="literal">RIGHT(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>len</code></em>)</code></a>
        </p><p>
          Returns the rightmost <em class="replaceable"><code>len</code></em>
          characters from the string <em class="replaceable"><code>str</code></em>, or
          <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT RIGHT('foobarbar', 4);</code></strong>
        -&gt; 'rbar'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_rpad"></a><p>
          <a class="indexterm" name="idm46444328469248"></a>

          <a class="link" href="functions.html#function_rpad"><code class="literal">RPAD(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>len</code></em>,<em class="replaceable"><code>padstr</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em>,
          right-padded with the string <em class="replaceable"><code>padstr</code></em>
          to a length of <em class="replaceable"><code>len</code></em> characters. If
          <em class="replaceable"><code>str</code></em> is longer than
          <em class="replaceable"><code>len</code></em>, the return value is shortened
          to <em class="replaceable"><code>len</code></em> characters.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT RPAD('hi',5,'?');</code></strong>
        -&gt; 'hi???'
mysql&gt; <strong class="userinput"><code>SELECT RPAD('hi',1,'?');</code></strong>
        -&gt; 'h'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_rtrim"></a><p>
          <a class="indexterm" name="idm46444328455168"></a>

          <a class="link" href="functions.html#function_rtrim"><code class="literal">RTRIM(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em> with
          trailing space characters removed.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT RTRIM('barbar   ');</code></strong>
        -&gt; 'barbar'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_soundex"></a><p>
          <a class="indexterm" name="idm46444328444864"></a>

          <a class="link" href="functions.html#function_soundex"><code class="literal">SOUNDEX(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns a soundex string from <em class="replaceable"><code>str</code></em>.
          Two strings that sound almost the same should have identical
          soundex strings. A standard soundex string is four characters
          long, but the <a class="link" href="functions.html#function_soundex"><code class="literal">SOUNDEX()</code></a>
          function returns an arbitrarily long string. You can use
          <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING()</code></a> on the result to
          get a standard soundex string. All nonalphabetic characters in
          <em class="replaceable"><code>str</code></em> are ignored. All international
          alphabetic characters outside the A-Z range are treated as
          vowels.
</p>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Important
</div>
<p>
            When using <a class="link" href="functions.html#function_soundex"><code class="literal">SOUNDEX()</code></a>, you
            should be aware of the following limitations:
</p>
</div>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              This function, as currently implemented, is intended to
              work well with strings that are in the English language
              only. Strings in other languages may not produce reliable
              results.
            </p></li><li class="listitem"><p>
              This function is not guaranteed to provide consistent
              results with strings that use multibyte character sets,
              including <code class="literal">utf-8</code>. See Bug #22638 for
              more information.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SOUNDEX('Hello');</code></strong>
        -&gt; 'H400'
mysql&gt; <strong class="userinput"><code>SELECT SOUNDEX('Quadratically');</code></strong>
        -&gt; 'Q36324'
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            This function implements the original Soundex algorithm, not
            the more popular enhanced version (also described by D.
            Knuth). The difference is that original version discards
            vowels first and duplicates second, whereas the enhanced
            version discards duplicates first and vowels second.
</p>
</div>
</li><li class="listitem"><a name="operator_sounds-like"></a><p>
          <a class="indexterm" name="idm46444328423856"></a>

          <a class="link" href="functions.html#operator_sounds-like"><code class="literal"><em class="replaceable"><code>expr1</code></em>
          SOUNDS LIKE <em class="replaceable"><code>expr2</code></em></code></a>
        </p><p>
          This is the same as
          <a class="link" href="functions.html#function_soundex"><code class="literal">SOUNDEX(<em class="replaceable"><code>expr1</code></em>)
          = SOUNDEX(<em class="replaceable"><code>expr2</code></em>)</code></a>.
        </p></li><li class="listitem"><a name="function_space"></a><p>
          <a class="indexterm" name="idm46444328414352"></a>

          <a class="link" href="functions.html#function_space"><code class="literal">SPACE(<em class="replaceable"><code>N</code></em>)</code></a>
        </p><p>
          Returns a string consisting of <em class="replaceable"><code>N</code></em>
          space characters.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SPACE(6);</code></strong>
        -&gt; '      '
</pre></li><li class="listitem"><a name="function_substr"></a><p>
          <a class="indexterm" name="idm46444328404528"></a>

          <a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>)</code></a>,
          <a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR(<em class="replaceable"><code>str</code></em>
          FROM <em class="replaceable"><code>pos</code></em>)</code></a>,
          <a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>,<em class="replaceable"><code>len</code></em>)</code></a>,
          <a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR(<em class="replaceable"><code>str</code></em>
          FROM <em class="replaceable"><code>pos</code></em> FOR
          <em class="replaceable"><code>len</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR()</code></a> is a synonym for
          <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING()</code></a>.
        </p></li><li class="listitem"><a name="function_substring"></a><p>
          <a class="indexterm" name="idm46444328387648"></a>

          <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>)</code></a>,
          <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING(<em class="replaceable"><code>str</code></em>
          FROM <em class="replaceable"><code>pos</code></em>)</code></a>,
          <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>pos</code></em>,<em class="replaceable"><code>len</code></em>)</code></a>,
          <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING(<em class="replaceable"><code>str</code></em>
          FROM <em class="replaceable"><code>pos</code></em> FOR
          <em class="replaceable"><code>len</code></em>)</code></a>
        </p><p>
          The forms without a <em class="replaceable"><code>len</code></em> argument
          return a substring from string <em class="replaceable"><code>str</code></em>
          starting at position <em class="replaceable"><code>pos</code></em>. The forms
          with a <em class="replaceable"><code>len</code></em> argument return a
          substring <em class="replaceable"><code>len</code></em> characters long from
          string <em class="replaceable"><code>str</code></em>, starting at position
          <em class="replaceable"><code>pos</code></em>. The forms that use
          <code class="literal">FROM</code> are standard SQL syntax. It is also
          possible to use a negative value for
          <em class="replaceable"><code>pos</code></em>. In this case, the beginning of
          the substring is <em class="replaceable"><code>pos</code></em> characters
          from the end of the string, rather than the beginning. A
          negative value may be used for <em class="replaceable"><code>pos</code></em>
          in any of the forms of this function. A value of 0 for
          <em class="replaceable"><code>pos</code></em> returns an empty string.
        </p><p>
          For all forms of <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING()</code></a>,
          the position of the first character in the string from which
          the substring is to be extracted is reckoned as
          <code class="literal">1</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING('Quadratically',5);</code></strong>
        -&gt; 'ratically'
mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING('foobarbar' FROM 4);</code></strong>
        -&gt; 'barbar'
mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING('Quadratically',5,6);</code></strong>
        -&gt; 'ratica'
mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING('Sakila', -3);</code></strong>
        -&gt; 'ila'
mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING('Sakila', -5, 3);</code></strong>
        -&gt; 'aki'
mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING('Sakila' FROM -4 FOR 2);</code></strong>
        -&gt; 'ki'
</pre><p>
          This function is multibyte safe.
        </p><p>
          If <em class="replaceable"><code>len</code></em> is less than 1, the result
          is the empty string.
        </p></li><li class="listitem"><a name="function_substring-index"></a><p>
          <a class="indexterm" name="idm46444328357424"></a>

          <a class="link" href="functions.html#function_substring-index"><code class="literal">SUBSTRING_INDEX(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>delim</code></em>,<em class="replaceable"><code>count</code></em>)</code></a>
        </p><p>
          Returns the substring from string
          <em class="replaceable"><code>str</code></em> before
          <em class="replaceable"><code>count</code></em> occurrences of the delimiter
          <em class="replaceable"><code>delim</code></em>. If
          <em class="replaceable"><code>count</code></em> is positive, everything to
          the left of the final delimiter (counting from the left) is
          returned. If <em class="replaceable"><code>count</code></em> is negative,
          everything to the right of the final delimiter (counting from
          the right) is returned.
          <a class="link" href="functions.html#function_substring-index"><code class="literal">SUBSTRING_INDEX()</code></a> performs a
          case-sensitive match when searching for
          <em class="replaceable"><code>delim</code></em>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);</code></strong>
        -&gt; 'www.mysql'
mysql&gt; <strong class="userinput"><code>SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);</code></strong>
        -&gt; 'mysql.com'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_to-base64"></a><p>
          <a class="indexterm" name="idm46444328341632"></a>

          <a class="link" href="functions.html#function_to-base64"><code class="literal">TO_BASE64(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Converts the string argument to base-64 encoded form and
          returns the result as a character string with the connection
          character set and collation. If the argument is not a string,
          it is converted to a string before conversion takes place. The
          result is <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>. Base-64 encoded strings can be
          decoded using the <a class="link" href="functions.html#function_from-base64"><code class="literal">FROM_BASE64()</code></a>
          function.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc'));</code></strong>
        -&gt; 'JWJj', 'abc'
</pre><p>
          Different base-64 encoding schemes exist. These are the
          encoding and decoding rules used by
          <a class="link" href="functions.html#function_to-base64"><code class="literal">TO_BASE64()</code></a> and
          <a class="link" href="functions.html#function_from-base64"><code class="literal">FROM_BASE64()</code></a>:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The encoding for alphabet value 62 is
              <code class="literal">'+'</code>.
            </p></li><li class="listitem"><p>
              The encoding for alphabet value 63 is
              <code class="literal">'/'</code>.
            </p></li><li class="listitem"><p>
              Encoded output consists of groups of 4 printable
              characters. Each 3 bytes of the input data are encoded
              using 4 characters. If the last group is incomplete, it is
              padded with <code class="literal">'='</code> characters to a length
              of 4.
            </p></li><li class="listitem"><p>
              A newline is added after each 76 characters of encoded
              output to divide long output into multiple lines.
            </p></li><li class="listitem"><p>
              Decoding recognizes and ignores newline, carriage return,
              tab, and space.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_trim"></a><p>
          <a class="indexterm" name="idm46444328318288"></a>

          <a class="link" href="functions.html#function_trim"><code class="literal">TRIM([{BOTH | LEADING | TRAILING}
          [<em class="replaceable"><code>remstr</code></em>] FROM]
          <em class="replaceable"><code>str</code></em>)</code></a>,
          <a class="link" href="functions.html#function_trim"><code class="literal">TRIM([<em class="replaceable"><code>remstr</code></em>
          FROM] <em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em> with all
          <em class="replaceable"><code>remstr</code></em> prefixes or suffixes
          removed. If none of the specifiers <code class="literal">BOTH</code>,
          <code class="literal">LEADING</code>, or <code class="literal">TRAILING</code> is
          given, <code class="literal">BOTH</code> is assumed.
          <em class="replaceable"><code>remstr</code></em> is optional and, if not
          specified, spaces are removed.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT TRIM('  bar   ');</code></strong>
        -&gt; 'bar'
mysql&gt; <strong class="userinput"><code>SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');</code></strong>
        -&gt; 'barxxx'
mysql&gt; <strong class="userinput"><code>SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');</code></strong>
        -&gt; 'bar'
mysql&gt; <strong class="userinput"><code>SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');</code></strong>
        -&gt; 'barx'
</pre><p>
          This function is multibyte safe.
        </p></li><li class="listitem"><a name="function_ucase"></a><p>
          <a class="indexterm" name="idm46444328299232"></a>

          <a class="link" href="functions.html#function_ucase"><code class="literal">UCASE(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_ucase"><code class="literal">UCASE()</code></a> is a synonym for
          <a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a>.
        </p><p>
          <code class="literal">UCASE()</code> used within views is rewritten as
          <code class="literal">UPPER()</code>.
        </p></li><li class="listitem"><a name="function_unhex"></a><p>
          <a class="indexterm" name="idm46444328287808"></a>

          <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          For a string argument <em class="replaceable"><code>str</code></em>,
          <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX(<em class="replaceable"><code>str</code></em>)</code></a>
          interprets each pair of characters in the argument as a
          hexadecimal number and converts it to the byte represented by
          the number. The return value is a binary string.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UNHEX('4D7953514C');</code></strong>
        -&gt; 'MySQL'
mysql&gt; <strong class="userinput"><code>SELECT X'4D7953514C';</code></strong>
        -&gt; 'MySQL'
mysql&gt; <strong class="userinput"><code>SELECT UNHEX(HEX('string'));</code></strong>
        -&gt; 'string'
mysql&gt; <strong class="userinput"><code>SELECT HEX(UNHEX('1267'));</code></strong>
        -&gt; '1267'
</pre><p>
          The characters in the argument string must be legal
          hexadecimal digits: <code class="literal">'0'</code> ..
          <code class="literal">'9'</code>, <code class="literal">'A'</code> ..
          <code class="literal">'F'</code>, <code class="literal">'a'</code> ..
          <code class="literal">'f'</code>. If the argument contains any
          nonhexadecimal digits, the result is <code class="literal">NULL</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UNHEX('GG');</code></strong>
+-------------+
| UNHEX('GG') |
+-------------+
| NULL        |
+-------------+
</pre><p>
          A <code class="literal">NULL</code> result can occur if the argument to
          <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a> is a
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a> column, because values
          are padded with 0x00 bytes when stored but those bytes are not
          stripped on retrieval. For example, <code class="literal">'41'</code> is
          stored into a <code class="literal">CHAR(3)</code> column as
          <code class="literal">'41 '</code> and retrieved as
          <code class="literal">'41'</code> (with the trailing pad space
          stripped), so <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a> for the
          column value returns <code class="literal">'A'</code>. By contrast
          <code class="literal">'41'</code> is stored into a
          <code class="literal">BINARY(3)</code> column as
          <code class="literal">'41\0'</code> and retrieved as
          <code class="literal">'41\0'</code> (with the trailing pad
          <code class="literal">0x00</code> byte not stripped).
          <code class="literal">'\0'</code> is not a legal hexadecimal digit, so
          <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a> for the column value
          returns <code class="literal">NULL</code>.
        </p><p>
          For a numeric argument <em class="replaceable"><code>N</code></em>, the
          inverse of
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX(<em class="replaceable"><code>N</code></em>)</code></a>
          is not performed by <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a>.
          Use
          <a class="link" href="functions.html#function_conv"><code class="literal">CONV(HEX(<em class="replaceable"><code>N</code></em>),16,10)</code></a>
          instead. See the description of
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a>.
        </p></li><li class="listitem"><a name="function_upper"></a><p>
          <a class="indexterm" name="idm46444328244928"></a>

          <a class="link" href="functions.html#function_upper"><code class="literal">UPPER(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the string <em class="replaceable"><code>str</code></em> with all
          characters changed to uppercase according to the current
          character set mapping. The default is
          <code class="literal">utf8mb4</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UPPER('Hej');</code></strong>
        -&gt; 'HEJ'
</pre><p>
          See the description of <a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a>
          for information that also applies to
          <a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a>. This included
          information about how to perform lettercase conversion of
          binary strings (<a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>,
          <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a>) for which these functions
          are ineffective, and information about case folding for
          Unicode character sets.
        </p><p>
          This function is multibyte safe.
        </p><p>
          <code class="literal">UCASE()</code> used within views is rewritten as
          <code class="literal">UPPER()</code>.
        </p></li><li class="listitem"><a name="function_weight-string"></a><p>
          <a class="indexterm" name="idm46444328225664"></a>

          <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING(<em class="replaceable"><code>str</code></em>
          [AS {CHAR|BINARY}(<em class="replaceable"><code>N</code></em>)]
          [<em class="replaceable"><code>flags</code></em>])</code></a>
        </p><p>
          This function returns the weight string for the input string.
          The return value is a binary string that represents the
          comparison and sorting value of the string. It has these
          properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If
              <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING(<em class="replaceable"><code>str1</code></em>)</code></a>
              =
              <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING(<em class="replaceable"><code>str2</code></em>)</code></a>,
              then <code class="literal"><em class="replaceable"><code>str1</code></em> =
              <em class="replaceable"><code>str2</code></em></code>
              (<em class="replaceable"><code>str1</code></em> and
              <em class="replaceable"><code>str2</code></em> are considered equal)
            </p></li><li class="listitem"><p>
              If
              <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING(<em class="replaceable"><code>str1</code></em>)</code></a>
              &lt;
              <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING(<em class="replaceable"><code>str2</code></em>)</code></a>,
              then <code class="literal"><em class="replaceable"><code>str1</code></em> &lt;
              <em class="replaceable"><code>str2</code></em></code>
              (<em class="replaceable"><code>str1</code></em> sorts before
              <em class="replaceable"><code>str2</code></em>)
</p></li></ul>
</div>
<p>
          <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING()</code></a> is a debugging
          function intended for internal use. Its behavior can change
          without notice between MySQL versions. It can be used for
          testing and debugging of collations, especially if you are
          adding a new collation. See
          <a class="xref" href="charset.html#adding-collation" title="10.14 Adding a Collation to a Character Set">Section 10.14, “Adding a Collation to a Character Set”</a>.
        </p><p>
          This list briefly summarizes the arguments. More details are
          given in the discussion following the list.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <em class="replaceable"><code>str</code></em>: The input string
              expression.
            </p></li><li class="listitem"><p>
              <code class="literal">AS</code> clause: Optional; cast the input
              string to a given type and length.
            </p></li><li class="listitem"><p>
              <em class="replaceable"><code>flags</code></em>: Optional; unused.
</p></li></ul>
</div>
<p>
          The input string, <em class="replaceable"><code>str</code></em>, is a string
          expression. If the input is a nonbinary (character) string
          such as a <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a>,
          <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>, or
          <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">TEXT</code></a> value, the return value
          contains the collation weights for the string. If the input is
          a binary (byte) string such as a
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>, or
          <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> value, the return value is
          the same as the input (the weight for each byte in a binary
          string is the byte value). If the input is
          <code class="literal">NULL</code>,
          <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING()</code></a> returns
          <code class="literal">NULL</code>.
        </p><p>
          Examples:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s = _utf8mb4 'AB' COLLATE utf8mb4_0900_ai_ci;</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));</code></strong>
+------+---------+------------------------+
| @s   | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| AB   | 4142    | 1C471C60               |
+------+---------+------------------------+
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s = _utf8mb4 'ab' COLLATE utf8mb4_0900_ai_ci;</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));</code></strong>
+------+---------+------------------------+
| @s   | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| ab   | 6162    | 1C471C60               |
+------+---------+------------------------+
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s = CAST('AB' AS BINARY);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));</code></strong>
+------+---------+------------------------+
| @s   | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| AB   | 4142    | 4142                   |
+------+---------+------------------------+
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s = CAST('ab' AS BINARY);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));</code></strong>
+------+---------+------------------------+
| @s   | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| ab   | 6162    | 6162                   |
+------+---------+------------------------+
</pre><p>
          The preceding examples use
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a> to display the
          <a class="link" href="functions.html#function_weight-string"><code class="literal">WEIGHT_STRING()</code></a> result. Because
          the result is a binary value,
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a> can be especially useful
          when the result contains nonprinting values, to display it in
          printable form:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s = CONVERT(X'C39F' USING utf8) COLLATE utf8_czech_ci;</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT HEX(WEIGHT_STRING(@s));</code></strong>
+------------------------+
| HEX(WEIGHT_STRING(@s)) |
+------------------------+
| 0FEA0FEA               |
+------------------------+
</pre><p>
          For non-<code class="literal">NULL</code> return values, the data type
          of the value is <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a> if
          its length is within the maximum length for
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>, otherwise the data
          type is <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a>.
        </p><p>
          The <code class="literal">AS</code> clause may be given to cast the
          input string to a nonbinary or binary string and to force it
          to a given length:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">AS CHAR(<em class="replaceable"><code>N</code></em>)</code>
              casts the string to a nonbinary string and pads it on the
              right with spaces to a length of
              <em class="replaceable"><code>N</code></em> characters.
              <em class="replaceable"><code>N</code></em> must be at least 1. If
              <em class="replaceable"><code>N</code></em> is less than the length of
              the input string, the string is truncated to
              <em class="replaceable"><code>N</code></em> characters. No warning occurs
              for truncation.
            </p></li><li class="listitem"><p>
              <code class="literal">AS BINARY(<em class="replaceable"><code>N</code></em>)</code>
              is similar but casts the string to a binary string,
              <em class="replaceable"><code>N</code></em> is measured in bytes (not
              characters), and padding uses <code class="literal">0x00</code>
              bytes (not spaces).
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET NAMES 'latin1';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4)));</code></strong>
+-------------------------------------+
| HEX(WEIGHT_STRING('ab' AS CHAR(4))) |
+-------------------------------------+
| 41422020                            |
+-------------------------------------+
mysql&gt; <strong class="userinput"><code>SET NAMES 'utf8';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4)));</code></strong>
+-------------------------------------+
| HEX(WEIGHT_STRING('ab' AS CHAR(4))) |
+-------------------------------------+
| 0041004200200020                    |
+-------------------------------------+
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(WEIGHT_STRING('ab' AS BINARY(4)));</code></strong>
+---------------------------------------+
| HEX(WEIGHT_STRING('ab' AS BINARY(4))) |
+---------------------------------------+
| 61620000                              |
+---------------------------------------+
</pre><p>
          The <em class="replaceable"><code>flags</code></em> clause currently is
          unused.
</p></li></ul>
</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="string-comparison-functions"></a>12.7.1 String Comparison Functions and Operators</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444328147824"></a><a class="indexterm" name="idm46444328146784"></a><a class="indexterm" name="idm46444328145296"></a><a class="indexterm" name="idm46444328144208"></a>
<div class="table">
<a name="idm46444328142720"></a><p class="title"><b>Table 12.12 String Comparison Functions and Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists string comparison functions and operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a></td>
<td>
      Simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_not-like"><code class="literal">NOT LIKE</code></a></td>
<td>
      Negation of simple pattern matching
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_strcmp"><code class="literal">STRCMP()</code></a></td>
<td>
      Compare two strings
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
        If a string function is given a binary string as an argument,
        the resulting string is also a binary string. A number converted
        to a string is treated as a binary string. This affects only
        comparisons.
      </p><a class="indexterm" name="idm46444328125200"></a><a class="indexterm" name="idm46444328123712"></a><p>
        Normally, if any expression in a string comparison is case
        sensitive, the comparison is performed in case-sensitive
        fashion.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_like"></a><p>
            <a class="indexterm" name="idm46444328118432"></a>

            <a class="link" href="functions.html#operator_like"><code class="literal"><em class="replaceable"><code>expr</code></em>
            LIKE <em class="replaceable"><code>pat</code></em> [ESCAPE
            '<em class="replaceable"><code>escape_char</code></em>']</code></a>
          </p><p>
            Pattern matching using an SQL pattern. Returns
            <code class="literal">1</code> (<code class="literal">TRUE</code>) or
            <code class="literal">0</code> (<code class="literal">FALSE</code>). If either
            <em class="replaceable"><code>expr</code></em> or
            <em class="replaceable"><code>pat</code></em> is <code class="literal">NULL</code>,
            the result is <code class="literal">NULL</code>.
          </p><p>
            The pattern need not be a literal string. For example, it
            can be specified as a string expression or table column.
          </p><p>
            Per the SQL standard, <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a>
            performs matching on a per-character basis, thus it can
            produce results different from the
            <a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a> comparison
            operator:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;</code></strong>
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;</code></strong>
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
|                                    1 |
+--------------------------------------+
</pre><p>
            In particular, trailing spaces are significant, which is not
            true for <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a> or
            <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a> comparisons performed
            with the <a class="link" href="functions.html#operator_equal"><code class="literal">=</code></a>
            operator:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'a' = 'a ', 'a' LIKE 'a ';</code></strong>
+------------+---------------+
| 'a' = 'a ' | 'a' LIKE 'a ' |
+------------+---------------+
|          1 |             0 |
+------------+---------------+
1 row in set (0.00 sec)
</pre><p>
            With <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a> you can use the
            following two wildcard characters in the pattern:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                <code class="literal">%</code> matches any number of characters,
                even zero characters.
              </p></li><li class="listitem"><p>
                <code class="literal">_</code> matches exactly one character.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'David!' LIKE 'David_';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 'David!' LIKE '%D%v%';</code></strong>
        -&gt; 1
</pre><p>
            To test for literal instances of a wildcard character,
            precede it by the escape character. If you do not specify
            the <code class="literal">ESCAPE</code> character,
            <code class="literal">\</code> is assumed.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                <code class="literal">\%</code> matches one <code class="literal">%</code>
                character.
              </p></li><li class="listitem"><p>
                <code class="literal">\_</code> matches one <code class="literal">_</code>
                character.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'David!' LIKE 'David\_';</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 'David_' LIKE 'David\_';</code></strong>
        -&gt; 1
</pre><p>
            To specify a different escape character, use the
            <code class="literal">ESCAPE</code> clause:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'David_' LIKE 'David|_' ESCAPE '|';</code></strong>
        -&gt; 1
</pre><p>
            The escape sequence should be empty or one character long.
            The expression must evaluate as a constant at execution
            time. If the
            <a class="link" href="server-administration.html#sqlmode_no_backslash_escapes"><code class="literal">NO_BACKSLASH_ESCAPES</code></a> SQL
            mode is enabled, the sequence cannot be empty.
          </p><p>
            The following two statements illustrate that string
            comparisons are not case-sensitive unless one of the
            operands is case-sensitive (uses a case-sensitive collation
            or is a binary string):
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'abc' LIKE 'ABC';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 'abc' LIKE _utf8mb4 'ABC' COLLATE utf8mb4_0900_as_cs;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 'abc' LIKE _utf8mb4 'ABC' COLLATE utf8mb4_bin;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 'abc' LIKE BINARY 'ABC';</code></strong>
        -&gt; 0
</pre><p>
            As an extension to standard SQL, MySQL permits
            <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a> on numeric expressions.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 10 LIKE '1%';</code></strong>
        -&gt; 1
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
              Because MySQL uses C escape syntax in strings (for
              example, <code class="literal">\n</code> to represent a newline
              character), you must double any <code class="literal">\</code> that
              you use in <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a> strings. For
              example, to search for <code class="literal">\n</code>, specify it
              as <code class="literal">\\n</code>. To search for
              <code class="literal">\</code>, specify it as
              <code class="literal">\\\\</code>; this is because the backslashes
              are stripped once by the parser and again when the pattern
              match is made, leaving a single backslash to be matched
              against.
            </p><p>
              Exception: At the end of the pattern string, backslash can
              be specified as <code class="literal">\\</code>. At the end of the
              string, backslash stands for itself because there is
              nothing following to escape. Suppose that a table contains
              the following values:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT filename FROM t1;</code></strong>
+--------------+
| filename     |
+--------------+
| C:           |
| C:\          |
| C:\Programs  |
| C:\Programs\ |
+--------------+
</pre><p>
              To test for values that end with backslash, you can match
              the values using either of the following patterns:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT filename, filename LIKE '%\\' FROM t1;</code></strong>
+--------------+---------------------+
| filename     | filename LIKE '%\\' |
+--------------+---------------------+
| C:           |                   0 |
| C:\          |                   1 |
| C:\Programs  |                   0 |
| C:\Programs\ |                   1 |
+--------------+---------------------+

mysql&gt; <strong class="userinput"><code>SELECT filename, filename LIKE '%\\\\' FROM t1;</code></strong>
+--------------+-----------------------+
| filename     | filename LIKE '%\\\\' |
+--------------+-----------------------+
| C:           |                     0 |
| C:\          |                     1 |
| C:\Programs  |                     0 |
| C:\Programs\ |                     1 |
+--------------+-----------------------+
</pre>
</div>
</li><li class="listitem"><a name="operator_not-like"></a><p>
            <a class="indexterm" name="idm46444328048704"></a>

            <a class="link" href="functions.html#operator_not-like"><code class="literal"><em class="replaceable"><code>expr</code></em>
            NOT LIKE <em class="replaceable"><code>pat</code></em> [ESCAPE
            '<em class="replaceable"><code>escape_char</code></em>']</code></a>
          </p><p>
            This is the same as <code class="literal">NOT
            (<em class="replaceable"><code>expr</code></em> LIKE
            <em class="replaceable"><code>pat</code></em> [ESCAPE
            '<em class="replaceable"><code>escape_char</code></em>'])</code>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
              Aggregate queries involving <a class="link" href="functions.html#operator_not-like"><code class="literal">NOT
              LIKE</code></a> comparisons with columns containing
              <code class="literal">NULL</code> may yield unexpected results. For
              example, consider the following table and data:
            </p><pre data-lang="sql" class="programlisting">CREATE TABLE foo (bar VARCHAR(10));

INSERT INTO foo VALUES (NULL), (NULL);</pre><p>
              The query <code class="literal">SELECT COUNT(*) FROM foo WHERE bar LIKE
              '%baz%';</code> returns <code class="literal">0</code>. You might
              assume that <code class="literal">SELECT COUNT(*) FROM foo WHERE bar
              NOT LIKE '%baz%';</code> would return
              <code class="literal">2</code>. However, this is not the case: The
              second query returns <code class="literal">0</code>. This is because
              <code class="literal">NULL NOT LIKE
              <em class="replaceable"><code>expr</code></em></code> always returns
              <code class="literal">NULL</code>, regardless of the value of
              <em class="replaceable"><code>expr</code></em>. The same is true for
              aggregate queries involving <code class="literal">NULL</code> and
              comparisons using
              <a class="link" href="functions.html#operator_not-regexp"><code class="literal">NOT
              RLIKE</code></a> or <a class="link" href="functions.html#operator_not-regexp"><code class="literal">NOT
              REGEXP</code></a>. In such cases, you must test explicitly
              for <code class="literal">NOT NULL</code> using
              <a class="link" href="functions.html#operator_or"><code class="literal">OR</code></a> (and not
              <a class="link" href="functions.html#operator_and"><code class="literal">AND</code></a>), as shown here:
</p><pre data-lang="sql" class="programlisting">SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%' OR bar IS NULL;</pre>
</div>
</li><li class="listitem"><a name="function_strcmp"></a><p>
            <a class="indexterm" name="idm46444328020976"></a>

            <a class="link" href="functions.html#function_strcmp"><code class="literal">STRCMP(<em class="replaceable"><code>expr1</code></em>,<em class="replaceable"><code>expr2</code></em>)</code></a>
          </p><p>
            <a class="link" href="functions.html#function_strcmp"><code class="literal">STRCMP()</code></a> returns
            <code class="literal">0</code> if the strings are the same,
            <code class="literal">-1</code> if the first argument is smaller than
            the second according to the current sort order, and
            <code class="literal">1</code> otherwise.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT STRCMP('text', 'text2');</code></strong>
        -&gt; -1
mysql&gt; <strong class="userinput"><code>SELECT STRCMP('text2', 'text');</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT STRCMP('text', 'text');</code></strong>
        -&gt; 0
</pre><p>
            <a class="link" href="functions.html#function_strcmp"><code class="literal">STRCMP()</code></a> performs the
            comparison using the collation of the arguments.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s1 = _utf8mb4 'x' COLLATE utf8mb4_0900_ai_ci;</code></strong>
mysql&gt; <strong class="userinput"><code>SET @s2 = _utf8mb4 'X' COLLATE utf8mb4_0900_ai_ci;</code></strong>
mysql&gt; <strong class="userinput"><code>SET @s3 = _utf8mb4 'x' COLLATE utf8mb4_0900_as_cs;</code></strong>
mysql&gt; <strong class="userinput"><code>SET @s4 = _utf8mb4 'X' COLLATE utf8mb4_0900_as_cs;</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT STRCMP(@s1, @s2), STRCMP(@s3, @s4);</code></strong>
+------------------+------------------+
| STRCMP(@s1, @s2) | STRCMP(@s3, @s4) |
+------------------+------------------+
|                0 |               -1 |
+------------------+------------------+
</pre><p>
            If the collations are incompatible, one of the arguments
            must be converted to be compatible with the other. See
            <a class="xref" href="charset.html#charset-collation-coercibility" title="10.8.4 Collation Coercibility in Expressions">Section 10.8.4, “Collation Coercibility in Expressions”</a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; SET @s1 = _utf8mb4 'x' COLLATE utf8mb4_0900_ai_ci;
mysql&gt; SET @s2 = _utf8mb4 'X' COLLATE utf8mb4_0900_ai_ci;
mysql&gt; SET @s3 = _utf8mb4 'x' COLLATE utf8mb4_0900_as_cs;
mysql&gt; SET @s4 = _utf8mb4 'X' COLLATE utf8mb4_0900_as_cs;
--&gt;
mysql&gt; <strong class="userinput"><code>SELECT STRCMP(@s1, @s3);</code></strong>
ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT)
and (utf8mb4_0900_as_cs,IMPLICIT) for operation 'strcmp'
mysql&gt; <strong class="userinput"><code>SELECT STRCMP(@s1, @s3 COLLATE utf8mb4_0900_ai_ci);</code></strong>
+---------------------------------------------+
| STRCMP(@s1, @s3 COLLATE utf8mb4_0900_ai_ci) |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
</pre></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="regexp"></a>12.7.2 Regular Expressions</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444327996096"></a><a class="indexterm" name="idm46444327995024"></a><a class="indexterm" name="idm46444327993936"></a>
<div class="table">
<a name="idm46444327992448"></a><p class="title"><b>Table 12.13 Regular Expression Functions and
Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists regular expression functions and operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_not-regexp"><code class="literal">NOT REGEXP</code></a></td>
<td>
      Negation of REGEXP
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">REGEXP</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-instr"><code class="literal">REGEXP_INSTR()</code></a></td>
<td>
      Starting index of substring matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-replace"><code class="literal">REGEXP_REPLACE()</code></a></td>
<td>
      Replace substrings matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_regexp-substr"><code class="literal">REGEXP_SUBSTR()</code></a></td>
<td>
      Return substring matching regular expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_regexp"><code class="literal">RLIKE</code></a></td>
<td>
      Whether string matches regular expression
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
        A regular expression is a powerful way of specifying a pattern
        for a complex search. This section discusses the functions and
        operators available for regular expression matching and
        illustrates, with examples, some of the special characters and
        constructs that can be used for regular expression operations.
        See also <a class="xref" href="tutorial.html#pattern-matching" title="3.3.4.7 Pattern Matching">Section 3.3.4.7, “Pattern Matching”</a>.
      </p><p>
        MySQL implements regular expression support using International
        Components for Unicode (ICU), which provides full Unicode
        support and is multibyte safe. (Prior to MySQL 8.0.4, MySQL used
        Henry Spencer's implementation of regular expressions, which
        operates in byte-wise fashion and is not multibyte safe. For
        information about ways in which applications that use regular
        expressions may be affected by the implementation change, see
        <a class="xref" href="functions.html#regexp-compatibility" title="Regular Expression Compatibility Considerations">Regular Expression Compatibility Considerations</a>.)
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><a class="xref" href="functions.html#regexp-operators" title="Regular Expression Functions and Operators">Regular Expression Functions and Operators</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#regexp-syntax" title="Regular Expression Syntax">Regular Expression Syntax</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#regexp-resource-control" title="Regular Expression Resource Control">Regular Expression Resource Control</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#regexp-compatibility" title="Regular Expression Compatibility Considerations">Regular Expression Compatibility Considerations</a></p></li></ul>
</div>

<div class="simplesect">

<div class="titlepage">
<div>

<div class="simple">
<h4 class="title"><a name="regexp-operators"></a>Regular Expression Functions and Operators</h4>

</div>

</div>

</div>

<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_not-regexp"></a><p>
              <a class="indexterm" name="idm46444327952416"></a>

              <a class="link" href="functions.html#operator_not-regexp"><code class="literal"><em class="replaceable"><code>expr</code></em>
              NOT REGEXP <em class="replaceable"><code>pat</code></em></code></a>,
              <a class="link" href="functions.html#operator_not-regexp"><code class="literal"><em class="replaceable"><code>expr</code></em>
              NOT RLIKE <em class="replaceable"><code>pat</code></em></code></a>
            </p><p>
              This is the same as <code class="literal">NOT
              (<em class="replaceable"><code>expr</code></em> REGEXP
              <em class="replaceable"><code>pat</code></em>)</code>.
            </p></li><li class="listitem"><a name="operator_regexp"></a><p>
              <a class="indexterm" name="idm46444327941056"></a>

              <a class="indexterm" name="idm46444327939984"></a>

              <a class="link" href="functions.html#operator_regexp"><code class="literal"><em class="replaceable"><code>expr</code></em>
              REGEXP <em class="replaceable"><code>pat</code></em></code></a>,
              <a class="link" href="functions.html#operator_regexp"><code class="literal"><em class="replaceable"><code>expr</code></em>
              RLIKE <em class="replaceable"><code>pat</code></em></code></a>
            </p><p>
              Returns 1 if the string <em class="replaceable"><code>expr</code></em>
              matches the regular expression specified by the pattern
              <em class="replaceable"><code>pat</code></em>, 0 otherwise. If
              <em class="replaceable"><code>expr</code></em> or
              <em class="replaceable"><code>pat</code></em> is <code class="literal">NULL</code>,
              the return value is <code class="literal">NULL</code>.
            </p><p>
              <a class="link" href="functions.html#operator_regexp"><code class="literal">REGEXP</code></a> and
              <a class="link" href="functions.html#operator_regexp"><code class="literal">RLIKE</code></a> are
              synonyms for <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
            </p><p>
              For additional information about how matching occurs, see
              the description for
              <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'Michael!' REGEXP '.*';</code></strong>
+------------------------+
| 'Michael!' REGEXP '.*' |
+------------------------+
|                      1 |
+------------------------+
mysql&gt; <strong class="userinput"><code>SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';</code></strong>
+---------------------------------------+
| 'new*\n*line' REGEXP 'new\\*.\\*line' |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT 'a' REGEXP '^[a-d]';</code></strong>
+---------------------+
| 'a' REGEXP '^[a-d]' |
+---------------------+
|                   1 |
+---------------------+
mysql&gt; <strong class="userinput"><code>SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A';</code></strong>
+----------------+-----------------------+
| 'a' REGEXP 'A' | 'a' REGEXP BINARY 'A' |
+----------------+-----------------------+
|              1 |                     0 |
+----------------+-----------------------+
</pre></li><li class="listitem"><a name="function_regexp-instr"></a><p>
              <a class="link" href="functions.html#function_regexp-instr"><code class="literal">REGEXP_INSTR(<em class="replaceable"><code>expr</code></em>,
              <em class="replaceable"><code>pat</code></em>[,
              <em class="replaceable"><code>pos</code></em>[,
              <em class="replaceable"><code>occurrence</code></em>[,
              <em class="replaceable"><code>return_option</code></em>[,
              <em class="replaceable"><code>match_type</code></em>]]]])</code></a>
            </p><a class="indexterm" name="idm46444327911488"></a><p>
              Returns the starting index of the substring of the string
              <em class="replaceable"><code>expr</code></em> that matches the regular
              expression specified by the pattern
              <em class="replaceable"><code>pat</code></em>, 0 if there is no match. If
              <em class="replaceable"><code>expr</code></em> or
              <em class="replaceable"><code>pat</code></em> is <code class="literal">NULL</code>,
              the return value is <code class="literal">NULL</code>. Character
              indexes begin at 1.
            </p><p>
              <a class="link" href="functions.html#function_regexp-instr"><code class="literal">REGEXP_INSTR()</code></a> takes these
              optional arguments:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                  <em class="replaceable"><code>pos</code></em>: The position in
                  <em class="replaceable"><code>expr</code></em> at which to start the
                  search. If omitted, the default is 1.
                </p></li><li class="listitem"><p>
                  <em class="replaceable"><code>occurrence</code></em>: Which
                  occurrence of a match to search for. If omitted, the
                  default is 1.
                </p></li><li class="listitem"><p>
                  <em class="replaceable"><code>return_option</code></em>: Which type
                  of position to return. If this value is 0,
                  <a class="link" href="functions.html#function_regexp-instr"><code class="literal">REGEXP_INSTR()</code></a> returns
                  the position of the matched substring's first
                  character. If this value is 1,
                  <a class="link" href="functions.html#function_regexp-instr"><code class="literal">REGEXP_INSTR()</code></a> returns
                  the position following the matched substring. If
                  omitted, the default is 0.
                </p></li><li class="listitem"><p>
                  <em class="replaceable"><code>match_type</code></em>: A string that
                  specifies how to perform matching. The meaning is as
                  described for
                  <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
</p></li></ul>
</div>
<p>
              For additional information about how matching occurs, see
              the description for
              <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('dog cat dog', 'dog');</code></strong>
+------------------------------------+
| REGEXP_INSTR('dog cat dog', 'dog') |
+------------------------------------+
|                                  1 |
+------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('dog cat dog', 'dog', 2);</code></strong>
+---------------------------------------+
| REGEXP_INSTR('dog cat dog', 'dog', 2) |
+---------------------------------------+
|                                     9 |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('aa aaa aaaa', 'a{2}');</code></strong>
+-------------------------------------+
| REGEXP_INSTR('aa aaa aaaa', 'a{2}') |
+-------------------------------------+
|                                   1 |
+-------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('aa aaa aaaa', 'a{4}');</code></strong>
+-------------------------------------+
| REGEXP_INSTR('aa aaa aaaa', 'a{4}') |
+-------------------------------------+
|                                   8 |
+-------------------------------------+
</pre></li><li class="listitem"><a name="function_regexp-like"></a><p>
              <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE(<em class="replaceable"><code>expr</code></em>,
              <em class="replaceable"><code>pat</code></em>[,
              <em class="replaceable"><code>match_type</code></em>])</code></a>
            </p><a class="indexterm" name="idm46444327880576"></a><p>
              Returns 1 if the string <em class="replaceable"><code>expr</code></em>
              matches the regular expression specified by the pattern
              <em class="replaceable"><code>pat</code></em>, 0 otherwise. If
              <em class="replaceable"><code>expr</code></em> or
              <em class="replaceable"><code>pat</code></em> is <code class="literal">NULL</code>,
              the return value is <code class="literal">NULL</code>.
            </p><p>
              The pattern can be an extended regular expression, the
              syntax for which is discussed in
              <a class="xref" href="functions.html#regexp-syntax" title="Regular Expression Syntax">Regular Expression Syntax</a>. The pattern need not be a
              literal string. For example, it can be specified as a
              string expression or table column.
            </p><p>
              The optional <em class="replaceable"><code>match_type</code></em>
              argument is a string that may contain any or all the
              following characters specifying how to perform matching:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                  <code class="literal">c</code>: Case sensitive matching.
                </p></li><li class="listitem"><p>
                  <code class="literal">i</code>: Case-insensitive matching.
                </p></li><li class="listitem"><p>
                  <code class="literal">m</code>: Multiple-line mode. Recognize
                  line terminators within the string. The default
                  behavior is to match line terminators only at the
                  start and end of the string expression.
                </p></li><li class="listitem"><p>
                  <code class="literal">n</code>: The <code class="literal">.</code>
                  character matches line terminators. The default is for
                  <code class="literal">.</code> matching to stop at the end of a
                  line.
                </p></li><li class="listitem"><p>
                  <code class="literal">u</code>: Unix-only line endings. Only the
                  newline character is recognized as a line ending by
                  the <code class="literal">.</code>, <code class="literal">^</code>, and
                  <code class="literal">$</code> match operators.
</p></li></ul>
</div>
<p>
              If characters specifying contradictory options are
              specified within <em class="replaceable"><code>match_type</code></em>,
              the rightmost one takes precedence.
            </p><p>
              By default, regular expression operations use the
              character set and collation of the
              <em class="replaceable"><code>expr</code></em> and
              <em class="replaceable"><code>pat</code></em> arguments when deciding the
              type of a character and performing the comparison. If the
              arguments have different character sets or collations,
              coercibility rules apply as described in
              <a class="xref" href="charset.html#charset-collation-coercibility" title="10.8.4 Collation Coercibility in Expressions">Section 10.8.4, “Collation Coercibility in Expressions”</a>.
              Arguments may be specified with explicit collation
              indicators to change comparison behavior.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('CamelCase', 'CAMELCASE');</code></strong>
+---------------------------------------+
| REGEXP_LIKE('CamelCase', 'CAMELCASE') |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('CamelCase', 'CAMELCASE' COLLATE utf8mb4_0900_as_cs);</code></strong>
+------------------------------------------------------------------+
| REGEXP_LIKE('CamelCase', 'CAMELCASE' COLLATE utf8mb4_0900_as_cs) |
+------------------------------------------------------------------+
|                                                                0 |
+------------------------------------------------------------------+
</pre><p>
              <em class="replaceable"><code>match_type</code></em> may be specified
              with the <code class="literal">c</code> or <code class="literal">i</code>
              characters to override the default case sensitivity.
              Exception: If either argument is a binary string, the
              arguments are handled in case-sensitive fashion as binary
              strings, even if <em class="replaceable"><code>match_type</code></em>
              contains the <code class="literal">i</code> character.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
                Because MySQL uses the C escape syntax in strings (for
                example, <code class="literal">\n</code> to represent the newline
                character), you must double any <code class="literal">\</code>
                that you use in your <em class="replaceable"><code>expr</code></em> and
                <em class="replaceable"><code>pat</code></em> arguments.
</p>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Michael!', '.*');</code></strong>
+-------------------------------+
| REGEXP_LIKE('Michael!', '.*') |
+-------------------------------+
|                             1 |
+-------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('new*\n*line', 'new\\*.\\*line');</code></strong>
+----------------------------------------------+
| REGEXP_LIKE('new*\n*line', 'new\\*.\\*line') |
+----------------------------------------------+
|                                            0 |
+----------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('a', '^[a-d]');</code></strong>
+----------------------------+
| REGEXP_LIKE('a', '^[a-d]') |
+----------------------------+
|                          1 |
+----------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('a', 'A'), REGEXP_LIKE('a', BINARY 'A');</code></strong>
+-----------------------+------------------------------+
| REGEXP_LIKE('a', 'A') | REGEXP_LIKE('a', BINARY 'A') |
+-----------------------+------------------------------+
|                     1 |                            0 |
+-----------------------+------------------------------+
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('abc', 'ABC');</code></strong>
+---------------------------+
| REGEXP_LIKE('abc', 'ABC') |
+---------------------------+
|                         1 |
+---------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('abc', 'ABC', 'c');</code></strong>
+--------------------------------+
| REGEXP_LIKE('abc', 'ABC', 'c') |
+--------------------------------+
|                              0 |
+--------------------------------+
</pre></li><li class="listitem"><a name="function_regexp-replace"></a><p>
              <a class="link" href="functions.html#function_regexp-replace"><code class="literal">REGEXP_REPLACE(<em class="replaceable"><code>expr</code></em>,
              <em class="replaceable"><code>pat</code></em>,
              <em class="replaceable"><code>repl</code></em>[,
              <em class="replaceable"><code>pos</code></em>[,
              <em class="replaceable"><code>occurrence</code></em>[,
              <em class="replaceable"><code>match_type</code></em>]]])</code></a>
            </p><a class="indexterm" name="idm46444327831424"></a><p>
              Replaces occurrences in the string
              <em class="replaceable"><code>expr</code></em> that match the regular
              expression specified by the pattern
              <em class="replaceable"><code>pat</code></em> with the replacement string
              <em class="replaceable"><code>repl</code></em>, and returns the resulting
              string. If <em class="replaceable"><code>expr</code></em>,
              <em class="replaceable"><code>pat</code></em>, or
              <em class="replaceable"><code>repl</code></em> is
              <code class="literal">NULL</code>, the return value is
              <code class="literal">NULL</code>.
            </p><p>
              <a class="link" href="functions.html#function_regexp-replace"><code class="literal">REGEXP_REPLACE()</code></a> takes
              these optional arguments:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                  <em class="replaceable"><code>pos</code></em>: The position in
                  <em class="replaceable"><code>expr</code></em> at which to start the
                  search. If omitted, the default is 1.
                </p></li><li class="listitem"><p>
                  <em class="replaceable"><code>occurrence</code></em>: Which
                  occurrence of a match to replace. If omitted, the
                  default is 0 (which means <span class="quote">“<span class="quote">replace all
                  occurrences</span>”</span>).
                </p></li><li class="listitem"><p>
                  <em class="replaceable"><code>match_type</code></em>: A string that
                  specifies how to perform matching. The meaning is as
                  described for
                  <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
</p></li></ul>
</div>
<p>
              Prior to MySQL 8.0.17, the result returned by this
              function used the <code class="literal">UTF-16</code> character set;
              in MySQL 8.0.17 and later, the character set and collation
              of the expression searched for matches is used. (Bug
              #94203, Bug #29308212)
            </p><p>
              For additional information about how matching occurs, see
              the description for
              <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_REPLACE('a b c', 'b', 'X');</code></strong>
+-----------------------------------+
| REGEXP_REPLACE('a b c', 'b', 'X') |
+-----------------------------------+
| a X c                             |
+-----------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3);</code></strong>
+----------------------------------------------------+
| REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3) |
+----------------------------------------------------+
| abc def X                                          |
+----------------------------------------------------+
</pre></li><li class="listitem"><a name="function_regexp-substr"></a><p>
              <a class="link" href="functions.html#function_regexp-substr"><code class="literal">REGEXP_SUBSTR(<em class="replaceable"><code>expr</code></em>,
              <em class="replaceable"><code>pat</code></em>[,
              <em class="replaceable"><code>pos</code></em>[,
              <em class="replaceable"><code>occurrence</code></em>[,
              <em class="replaceable"><code>match_type</code></em>]]])</code></a>
            </p><a class="indexterm" name="idm46444327803040"></a><p>
              Returns the substring of the string
              <em class="replaceable"><code>expr</code></em> that matches the regular
              expression specified by the pattern
              <em class="replaceable"><code>pat</code></em>, <code class="literal">NULL</code> if
              there is no match. If <em class="replaceable"><code>expr</code></em> or
              <em class="replaceable"><code>pat</code></em> is <code class="literal">NULL</code>,
              the return value is <code class="literal">NULL</code>.
            </p><p>
              <a class="link" href="functions.html#function_regexp-substr"><code class="literal">REGEXP_SUBSTR()</code></a> takes these
              optional arguments:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                  <em class="replaceable"><code>pos</code></em>: The position in
                  <em class="replaceable"><code>expr</code></em> at which to start the
                  search. If omitted, the default is 1.
                </p></li><li class="listitem"><p>
                  <em class="replaceable"><code>occurrence</code></em>: Which
                  occurrence of a match to search for. If omitted, the
                  default is 1.
                </p></li><li class="listitem"><p>
                  <em class="replaceable"><code>match_type</code></em>: A string that
                  specifies how to perform matching. The meaning is as
                  described for
                  <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
</p></li></ul>
</div>
<p>
              Prior to MySQL 8.0.17, the result returned by this
              function used the <code class="literal">UTF-16</code> character set;
              in MySQL 8.0.17 and later, the character set and collation
              of the expression searched for matches is used. (Bug
              #94203, Bug #29308212)
            </p><p>
              For additional information about how matching occurs, see
              the description for
              <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a>.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+');</code></strong>
+----------------------------------------+
| REGEXP_SUBSTR('abc def ghi', '[a-z]+') |
+----------------------------------------+
| abc                                    |
+----------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3);</code></strong>
+----------------------------------------------+
| REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3) |
+----------------------------------------------+
| ghi                                          |
+----------------------------------------------+
</pre></li></ul>
</div>

</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="regexp-syntax"></a>Regular Expression Syntax</h4>

</div>

</div>

</div>
<p>
          A regular expression describes a set of strings. The simplest
          regular expression is one that has no special characters in
          it. For example, the regular expression
          <code class="literal">hello</code> matches <code class="literal">hello</code> and
          nothing else.
        </p><p>
          Nontrivial regular expressions use certain special constructs
          so that they can match more than one string. For example, the
          regular expression <code class="literal">hello|world</code> contains the
          <code class="literal">|</code> alternation operator and matches either
          the <code class="literal">hello</code> or <code class="literal">world</code>.
        </p><p>
          As a more complex example, the regular expression
          <code class="literal">B[an]*s</code> matches any of the strings
          <code class="literal">Bananas</code>, <code class="literal">Baaaaas</code>,
          <code class="literal">Bs</code>, and any other string starting with a
          <code class="literal">B</code>, ending with an <code class="literal">s</code>, and
          containing any number of <code class="literal">a</code> or
          <code class="literal">n</code> characters in between.
        </p><p>
          The following list covers some of the basic special characters
          and constructs that can be used in regular expressions. For
          information about the full regular expression syntax supported
          by the ICU library used to implement regular expression
          support, visit the
          <a class="ulink" href="http://userguide.icu-project.org/strings/regexp" target="_top">
          International Components for Unicode website</a>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
              <code class="literal">^</code>
            </p><p>
              Match the beginning of a string.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fo\nfo', '^fo$');</code></strong>                   -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fofo', '^fo');</code></strong>                      -&gt; 1
</pre></li><li class="listitem"><p>
              <code class="literal">$</code>
            </p><p>
              Match the end of a string.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fo\no', '^fo\no$');</code></strong>                 -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fo\no', '^fo$');</code></strong>                    -&gt; 0
</pre></li><li class="listitem"><p>
              <code class="literal">.</code>
            </p><p>
              Match any character (including carriage return and
              newline, although to match these in the middle of a
              string, the <code class="literal">m</code> (multiple line)
              match-control character or the <code class="literal">(?m)</code>
              within-pattern modifier must be given).
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fofo', '^f.*$');</code></strong>                    -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fo\r\nfo', '^f.*$');</code></strong>                -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fo\r\nfo', '^f.*$', 'm');</code></strong>           -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('fo\r\nfo', '(?m)^f.*$');</code></strong>           -&gt; 1
</pre></li><li class="listitem"><p>
              <code class="literal">a*</code>
            </p><p>
              Match any sequence of zero or more <code class="literal">a</code>
              characters.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Ban', '^Ba*n');</code></strong>                     -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Baaan', '^Ba*n');</code></strong>                   -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Bn', '^Ba*n');</code></strong>                      -&gt; 1
</pre></li><li class="listitem"><p>
              <code class="literal">a+</code>
            </p><p>
              Match any sequence of one or more <code class="literal">a</code>
              characters.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Ban', '^Ba+n');</code></strong>                     -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Bn', '^Ba+n');</code></strong>                      -&gt; 0
</pre></li><li class="listitem"><p>
              <code class="literal">a?</code>
            </p><p>
              Match either zero or one <code class="literal">a</code> character.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Bn', '^Ba?n');</code></strong>                      -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Ban', '^Ba?n');</code></strong>                     -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('Baan', '^Ba?n');</code></strong>                    -&gt; 0
</pre></li><li class="listitem"><p>
              <code class="literal">de|abc</code>
            </p><p>
              Alternation; match either of the sequences
              <code class="literal">de</code> or <code class="literal">abc</code>.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('pi', 'pi|apa');</code></strong>                     -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('axe', 'pi|apa');</code></strong>                    -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('apa', 'pi|apa');</code></strong>                    -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('apa', '^(pi|apa)$');</code></strong>                -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('pi', '^(pi|apa)$');</code></strong>                 -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('pix', '^(pi|apa)$');</code></strong>                -&gt; 0
</pre></li><li class="listitem"><p>
              <code class="literal">(abc)*</code>
            </p><p>
              Match zero or more instances of the sequence
              <code class="literal">abc</code>.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('pi', '^(pi)*$');</code></strong>                    -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('pip', '^(pi)*$');</code></strong>                   -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('pipi', '^(pi)*$');</code></strong>                  -&gt; 1
</pre></li><li class="listitem"><p>
              <code class="literal">{1}</code>, <code class="literal">{2,3}</code>
            </p><p>
              Repetition;
              <code class="literal">{<em class="replaceable"><code>n</code></em>}</code> and
              <code class="literal">{<em class="replaceable"><code>m</code></em>,<em class="replaceable"><code>n</code></em>}</code>
              notation provide a more general way of writing regular
              expressions that match many occurrences of the previous
              atom (or <span class="quote">“<span class="quote">piece</span>”</span>) of the pattern.
              <em class="replaceable"><code>m</code></em> and
              <em class="replaceable"><code>n</code></em> are integers.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                  <code class="literal">a*</code>
                </p><p>
                  Can be written as <code class="literal">a{0,}</code>.
                </p></li><li class="listitem"><p>
                  <code class="literal">a+</code>
                </p><p>
                  Can be written as <code class="literal">a{1,}</code>.
                </p></li><li class="listitem"><p>
                  <code class="literal">a?</code>
                </p><p>
                  Can be written as <code class="literal">a{0,1}</code>.
</p></li></ul>
</div>
<p>
              To be more precise,
              <code class="literal">a{<em class="replaceable"><code>n</code></em>}</code> matches
              exactly <em class="replaceable"><code>n</code></em> instances of
              <code class="literal">a</code>.
              <code class="literal">a{<em class="replaceable"><code>n</code></em>,}</code>
              matches <em class="replaceable"><code>n</code></em> or more instances of
              <code class="literal">a</code>.
              <code class="literal">a{<em class="replaceable"><code>m</code></em>,<em class="replaceable"><code>n</code></em>}</code>
              matches <em class="replaceable"><code>m</code></em> through
              <em class="replaceable"><code>n</code></em> instances of
              <code class="literal">a</code>, inclusive. If both
              <em class="replaceable"><code>m</code></em> and
              <em class="replaceable"><code>n</code></em> are given,
              <em class="replaceable"><code>m</code></em> must be less than or equal to
              <em class="replaceable"><code>n</code></em>.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('abcde', 'a[bcd]{2}e');</code></strong>              -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('abcde', 'a[bcd]{3}e');</code></strong>              -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('abcde', 'a[bcd]{1,10}e');</code></strong>           -&gt; 1
</pre></li><li class="listitem"><p>
              <code class="literal">[a-dX]</code>, <code class="literal">[^a-dX]</code>
            </p><p>
              Matches any character that is (or is not, if
              <code class="literal">^</code> is used) either <code class="literal">a</code>,
              <code class="literal">b</code>, <code class="literal">c</code>,
              <code class="literal">d</code> or <code class="literal">X</code>. A
              <code class="literal">-</code> character between two other
              characters forms a range that matches all characters from
              the first character to the second. For example,
              <code class="literal">[0-9]</code> matches any decimal digit. To
              include a literal <code class="literal">]</code> character, it must
              immediately follow the opening bracket
              <code class="literal">[</code>. To include a literal
              <code class="literal">-</code> character, it must be written first
              or last. Any character that does not have a defined
              special meaning inside a <code class="literal">[]</code> pair
              matches only itself.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('aXbc', '[a-dXYZ]');</code></strong>                 -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('aXbc', '^[a-dXYZ]$');</code></strong>               -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('aXbc', '^[a-dXYZ]+$');</code></strong>              -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('aXbc', '^[^a-dXYZ]+$');</code></strong>             -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('gheis', '^[^a-dXYZ]+$');</code></strong>            -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('gheisa', '^[^a-dXYZ]+$');</code></strong>           -&gt; 0
</pre></li><li class="listitem"><p>
              <code class="literal">[=character_class=]</code>
            </p><p>
              Within a bracket expression (written using
              <code class="literal">[</code> and <code class="literal">]</code>),
              <code class="literal">[=character_class=]</code> represents an
              equivalence class. It matches all characters with the same
              collation value, including itself. For example, if
              <code class="literal">o</code> and <code class="literal">(+)</code> are the
              members of an equivalence class,
              <code class="literal">[[=o=]]</code>, <code class="literal">[[=(+)=]]</code>,
              and <code class="literal">[o(+)]</code> are all synonymous. An
              equivalence class may not be used as an endpoint of a
              range.
            </p></li><li class="listitem"><p>
              <code class="literal">[:character_class:]</code>
            </p><p>
              Within a bracket expression (written using
              <code class="literal">[</code> and <code class="literal">]</code>),
              <code class="literal">[:character_class:]</code> represents a
              character class that matches all characters belonging to
              that class. The following table lists the standard class
              names. These names stand for the character classes defined
              in the <code class="literal">ctype(3)</code> manual page. A
              particular locale may provide other class names. A
              character class may not be used as an endpoint of a range.
</p>
<div class="informaltable">
<table summary="Character class names and the meaning of each class."><col width="20%"><col width="80%"><thead><tr>
                  <th scope="col">Character Class Name</th>
                  <th scope="col">Meaning</th>
                </tr></thead><tbody><tr>
                  <td scope="row"><code class="literal">alnum</code></td>
                  <td>Alphanumeric characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">alpha</code></td>
                  <td>Alphabetic characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">blank</code></td>
                  <td>Whitespace characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">cntrl</code></td>
                  <td>Control characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">digit</code></td>
                  <td>Digit characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">graph</code></td>
                  <td>Graphic characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">lower</code></td>
                  <td>Lowercase alphabetic characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">print</code></td>
                  <td>Graphic or space characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">punct</code></td>
                  <td>Punctuation characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">space</code></td>
                  <td>Space, tab, newline, and carriage return</td>
                </tr><tr>
                  <td scope="row"><code class="literal">upper</code></td>
                  <td>Uppercase alphabetic characters</td>
                </tr><tr>
                  <td scope="row"><code class="literal">xdigit</code></td>
                  <td>Hexadecimal digit characters</td>
</tr></tbody></table>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('justalnums', '[[:alnum:]]+');</code></strong>       -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('!!', '[[:alnum:]]+');</code></strong>               -&gt; 0
</pre></li></ul>
</div>
<p>
          To use a literal instance of a special character in a regular
          expression, precede it by two backslash (\) characters. The
          MySQL parser interprets one of the backslashes, and the
          regular expression library interprets the other. For example,
          to match the string <code class="literal">1+2</code> that contains the
          special <code class="literal">+</code> character, only the last of the
          following regular expressions is the correct one:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('1+2', '1+2');</code></strong>                       -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('1+2', '1\+2');</code></strong>                      -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('1+2', '1\\+2');</code></strong>                     -&gt; 1
</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="regexp-resource-control"></a>Regular Expression Resource Control</h4>

</div>

</div>

</div>
<p>
          <a class="link" href="functions.html#function_regexp-like"><code class="literal">REGEXP_LIKE()</code></a> and similar
          functions use resources that can be controlled by setting
          system variables:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
              The match engine uses memory for its internal stack. To
              control the maximum available memory for the stack in
              bytes, set the
              <a class="link" href="server-administration.html#sysvar_regexp_stack_limit"><code class="literal">regexp_stack_limit</code></a> system
              variable.
            </p></li><li class="listitem"><p>
              The match engine operates in steps. To control the maximum
              number of steps performed by the engine (and thus
              indirectly the execution time), set the
              <a class="link" href="server-administration.html#sysvar_regexp_time_limit"><code class="literal">regexp_time_limit</code></a> system
              variable. Because this limit is expressed as number of
              steps, it affects execution time only indirectly.
              Typically, it is on the order of milliseconds.
</p></li></ul>
</div>

</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="regexp-compatibility"></a>Regular Expression Compatibility Considerations</h4>

</div>

</div>

</div>
<p>
          Prior to MySQL 8.0.4, MySQL used the Henry Spencer regular
          expression library to support regular expression operations,
          rather than International Components for Unicode (ICU). The
          following discussion describes differences between the Spencer
          and ICU libraries that may affect applications:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
              With the Spencer library, the
              <a class="link" href="functions.html#operator_regexp"><code class="literal">REGEXP</code></a> and
              <a class="link" href="functions.html#operator_regexp"><code class="literal">RLIKE</code></a>
              operators work in byte-wise fashion, so they are not
              multibyte safe and may produce unexpected results with
              multibyte character sets. In addition, these operators
              compare characters by their byte values and accented
              characters may not compare as equal even if a given
              collation treats them as equal.
            </p><p>
              ICU has full Unicode support and is multibyte safe. Its
              regular expression functions treat all strings as
              <code class="literal">UTF-16</code>. You should keep in mind that
              positional indexes are based on 16-bit chunks and not on
              code points. This means that, when passed to such
              functions, characters using more than one chunk may
              produce unanticipated results, such as those shown here:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('🍣🍣b', 'b');</code></strong>
+--------------------------+
| REGEXP_INSTR('??b', 'b') |
+--------------------------+
|                        5 |
+--------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('🍣🍣bxxx', 'b', 4);</code></strong>
+--------------------------------+
| REGEXP_INSTR('??bxxx', 'b', 4) |
+--------------------------------+
|                              5 |
+--------------------------------+
1 row in set (0.00 sec)
</pre><p>
              Characters within the Unicode Basic Multilingual Plane,
              which includes characters used by most modern languages,
              are safe in this regard:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('бжb', 'b');</code></strong>
+----------------------------+
| REGEXP_INSTR('бжb', 'b')   |
+----------------------------+
|                          3 |
+----------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('עבb', 'b');</code></strong>
+----------------------------+
| REGEXP_INSTR('עבb', 'b')   |
+----------------------------+
|                          3 |
+----------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT REGEXP_INSTR('µå周çб', '周');</code></strong>
+------------------------------------+
| REGEXP_INSTR('µå周çб', '周')       |
+------------------------------------+
|                                  3 |
+------------------------------------+
1 row in set (0.00 sec)
</pre><p>
              Emoji, such as the <span class="quote">“<span class="quote">sushi</span>”</span> character
              <code class="literal">🍣</code> (U+1F363) used in the first two
              examples, are not included in the Basic Multilingual
              Plane, but rather in Unicode's Supplementary
              Multilingual Plane. Another issue can arise with emoji and
              other 4-byte characters when
              <a class="link" href="functions.html#function_regexp-substr"><code class="literal">REGEXP_SUBSTR()</code></a> or a
              similar function begins searching in the middle of a
              character. Each of the two statements in the following
              example starts from the second 2-byte position in the
              first argument. The first statement works on a string
              consisting solely of 2-byte (BMP) characters. The second
              statement contains 4-byte characters which are incorrectly
              interpreted in the result because the first two bytes are
              stripped off and so the remainder of the character data is
              misaligned.
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_SUBSTR('周周周周', '.*', 2);</code></strong>
+----------------------------------------+
| REGEXP_SUBSTR('周周周周', '.*', 2)     |
+----------------------------------------+
| 周周周                                 |
+----------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT REGEXP_SUBSTR('🍣🍣🍣🍣', '.*', 2);</code></strong>
+--------------------------------+
| REGEXP_SUBSTR('????', '.*', 2) |
+--------------------------------+
| ?㳟揘㳟揘㳟揘                  |
+--------------------------------+
1 row in set (0.00 sec)
</pre></li><li class="listitem"><p>
              For the <code class="literal">.</code> operator, the Spencer library
              matches line-terminator characters (carriage return,
              newline) anywhere in string expressions, including in the
              middle. To match line terminator characters in the middle
              of strings with ICU, specify the <code class="literal">m</code>
              match-control character.
            </p></li><li class="listitem"><p>
              The Spencer library supports word-beginning and word-end
              boundary markers (<code class="literal">[[:&lt;:]]</code> and
              <code class="literal">[[:&gt;:]]</code> notation). ICU does not. For
              ICU, you can use <code class="literal">\b</code> to match word
              boundaries; double the backslash because MySQL interprets
              it as the escape character within strings.
            </p></li><li class="listitem"><p>
              The Spencer library supports collating element bracket
              expressions (<code class="literal">[.characters.]</code> notation).
              ICU does not.
            </p></li><li class="listitem"><p>
              For repetition counts (<code class="literal">{n}</code> and
              <code class="literal">{m,n}</code> notation), the Spencer library
              has a maximum of 255. ICU has no such limit, although the
              maximum number of match engine steps can be limited by
              setting the
              <a class="link" href="server-administration.html#sysvar_regexp_time_limit"><code class="literal">regexp_time_limit</code></a> system
              variable.
            </p></li><li class="listitem"><p>
              ICU interprets parentheses as metacharacters. To specify a
              literal open or close parenthesis <code class="literal">(</code> in
              a regular expression, it must be escaped:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('(', '(');</code></strong>
ERROR 3692 (HY000): Mismatched parenthesis in regular expression.
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('(', '\\(');</code></strong>
+-------------------------+
| REGEXP_LIKE('(', '\\(') |
+-------------------------+
|                       1 |
+-------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE(')', ')');</code></strong>
ERROR 3692 (HY000): Mismatched parenthesis in regular expression.
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE(')', '\\)');</code></strong>
+-------------------------+
| REGEXP_LIKE(')', '\\)') |
+-------------------------+
|                       1 |
+-------------------------+
</pre></li><li class="listitem"><p>
              ICU also interprets square brackets as metacharacters, but
              only the opening square bracket need be escaped to be used
              as a literal character:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('[', '[');</code></strong>
ERROR 3696 (HY000): The regular expression contains an
unclosed bracket expression.
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE('[', '\\[');</code></strong>
+-------------------------+
| REGEXP_LIKE('[', '\\[') |
+-------------------------+
|                       1 |
+-------------------------+
mysql&gt; <strong class="userinput"><code>SELECT REGEXP_LIKE(']', ']');</code></strong>
+-----------------------+
| REGEXP_LIKE(']', ']') |
+-----------------------+
|                     1 |
+-----------------------+
</pre></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="string-functions-charset"></a>12.7.3 Character Set and Collation of Function Results</h3>

</div>

</div>

</div>
<p>
        MySQL has many operators and functions that return a string.
        This section answers the question: What is the character set and
        collation of such a string?
      </p><p>
        For simple functions that take string input and return a string
        result as output, the output's character set and collation are
        the same as those of the principal input value. For example,
        <a class="link" href="functions.html#function_upper"><code class="literal">UPPER(<em class="replaceable"><code>X</code></em>)</code></a>
        returns a string with the same character string and collation as
        <em class="replaceable"><code>X</code></em>. The same applies for
        <a class="link" href="functions.html#function_instr"><code class="literal">INSTR()</code></a>,
        <a class="link" href="functions.html#function_lcase"><code class="literal">LCASE()</code></a>,
        <a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a>,
        <a class="link" href="functions.html#function_ltrim"><code class="literal">LTRIM()</code></a>,
        <a class="link" href="functions.html#function_mid"><code class="literal">MID()</code></a>,
        <a class="link" href="functions.html#function_repeat"><code class="literal">REPEAT()</code></a>,
        <a class="link" href="functions.html#function_replace"><code class="literal">REPLACE()</code></a>,
        <a class="link" href="functions.html#function_reverse"><code class="literal">REVERSE()</code></a>,
        <a class="link" href="functions.html#function_right"><code class="literal">RIGHT()</code></a>,
        <a class="link" href="functions.html#function_rpad"><code class="literal">RPAD()</code></a>,
        <a class="link" href="functions.html#function_rtrim"><code class="literal">RTRIM()</code></a>,
        <a class="link" href="functions.html#function_soundex"><code class="literal">SOUNDEX()</code></a>,
        <a class="link" href="functions.html#function_substring"><code class="literal">SUBSTRING()</code></a>,
        <a class="link" href="functions.html#function_trim"><code class="literal">TRIM()</code></a>,
        <a class="link" href="functions.html#function_ucase"><code class="literal">UCASE()</code></a>, and
        <a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          The <a class="link" href="functions.html#function_replace"><code class="literal">REPLACE()</code></a> function, unlike
          all other functions, always ignores the collation of the
          string input and performs a case-sensitive comparison.
</p>
</div>
<p>
        If a string input or function result is a binary string, the
        string has the <code class="literal">binary</code> character set and
        collation. This can be checked by using the
        <a class="link" href="functions.html#function_charset"><code class="literal">CHARSET()</code></a> and
        <a class="link" href="functions.html#function_collation"><code class="literal">COLLATION()</code></a> functions, both of
        which return <code class="literal">binary</code> for a binary string
        argument:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CHARSET(BINARY 'a'), COLLATION(BINARY 'a');</code></strong>
+---------------------+-----------------------+
| CHARSET(BINARY 'a') | COLLATION(BINARY 'a') |
+---------------------+-----------------------+
| binary              | binary                |
+---------------------+-----------------------+
</pre><p>
        For operations that combine multiple string inputs and return a
        single string output, the <span class="quote">“<span class="quote">aggregation rules</span>”</span> of
        standard SQL apply for determining the collation of the result:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If an explicit <code class="literal">COLLATE
            <em class="replaceable"><code>Y</code></em></code> occurs, use
            <em class="replaceable"><code>Y</code></em>.
          </p></li><li class="listitem"><p>
            If explicit <code class="literal">COLLATE
            <em class="replaceable"><code>Y</code></em></code> and <code class="literal">COLLATE
            <em class="replaceable"><code>Z</code></em></code> occur, raise an
            error.
          </p></li><li class="listitem"><p>
            Otherwise, if all collations are
            <em class="replaceable"><code>Y</code></em>, use
            <em class="replaceable"><code>Y</code></em>.
          </p></li><li class="listitem"><p>
            Otherwise, the result has no collation.
</p></li></ul>
</div>
<p>
        For example, with <code class="literal">CASE ... WHEN a THEN b WHEN b THEN c
        COLLATE <em class="replaceable"><code>X</code></em> END</code>, the
        resulting collation is <em class="replaceable"><code>X</code></em>. The same
        applies for <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a>,
        <a class="link" href="functions.html#operator_or"><code class="literal">||</code></a>,
        <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a>,
        <a class="link" href="functions.html#function_elt"><code class="literal">ELT()</code></a>,
        <a class="link" href="functions.html#function_greatest"><code class="literal">GREATEST()</code></a>,
        <a class="link" href="functions.html#function_if"><code class="literal">IF()</code></a>, and
        <a class="link" href="functions.html#function_least"><code class="literal">LEAST()</code></a>.
      </p><p>
        For operations that convert to character data, the character set
        and collation of the strings that result from the operations are
        defined by the
        <a class="link" href="server-administration.html#sysvar_character_set_connection"><code class="literal">character_set_connection</code></a> and
        <a class="link" href="server-administration.html#sysvar_collation_connection"><code class="literal">collation_connection</code></a> system
        variables that determine the default connection character set
        and collation (see <a class="xref" href="charset.html#charset-connection" title="10.4 Connection Character Sets and Collations">Section 10.4, “Connection Character Sets and Collations”</a>). This
        applies only to <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a>,
        <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a>,
        <a class="link" href="functions.html#function_conv"><code class="literal">CONV()</code></a>,
        <a class="link" href="functions.html#function_format"><code class="literal">FORMAT()</code></a>,
        <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a>, and
        <a class="link" href="functions.html#function_space"><code class="literal">SPACE()</code></a>.
      </p><p>
        An exception to the preceding priniciple occurs for expressions
        for virtual generated columns. In such expressions, the table
        character set is used for
        <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a>,
        <a class="link" href="functions.html#function_conv"><code class="literal">CONV()</code></a>, or
        <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a> results, regardless of
        connection character set.
      </p><p>
        If there is any question about the character set or collation of
        the result returned by a string function, use the
        <a class="link" href="functions.html#function_charset"><code class="literal">CHARSET()</code></a> or
        <a class="link" href="functions.html#function_collation"><code class="literal">COLLATION()</code></a> function to find out:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT USER(), CHARSET(USER()), COLLATION(USER());</code></strong>
+----------------+-----------------+-------------------+
| USER()         | CHARSET(USER()) | COLLATION(USER()) |
+----------------+-----------------+-------------------+
| test@localhost | utf8            | utf8_general_ci   |
+----------------+-----------------+-------------------+
mysql&gt; <strong class="userinput"><code>SELECT CHARSET(COMPRESS('abc')), COLLATION(COMPRESS('abc'));</code></strong>
+--------------------------+----------------------------+
| CHARSET(COMPRESS('abc')) | COLLATION(COMPRESS('abc')) |
+--------------------------+----------------------------+
| binary                   | binary                     |
+--------------------------+----------------------------+
</pre>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="mysql-calendar"></a>12.8 What Calendar Is Used By MySQL?</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444327484624"></a><p>
      MySQL uses what is known as a <span class="firstterm">proleptic
      Gregorian calendar</span>.
    </p><p>
      Every country that has switched from the Julian to the Gregorian
      calendar has had to discard at least ten days during the switch.
      To see how this works, consider the month of October 1582, when
      the first Julian-to-Gregorian switch occurred.
</p>
<div class="informaltable">
<table summary="The month of October 1582, when the first Julian-to-Gregorian switch occurred. Table headings are days of the week and table rows list the dates for each day of the week. The table is intended to illustrate that there are no dates between October 4 and October 15."><col width="14%"><col width="14%"><col width="14%"><col width="14%"><col width="14%"><col width="14%"><col width="14%"><thead><tr>
          <th scope="col">Monday</th>
          <th scope="col">Tuesday</th>
          <th scope="col">Wednesday</th>
          <th scope="col">Thursday</th>
          <th scope="col">Friday</th>
          <th scope="col">Saturday</th>
          <th scope="col">Sunday</th>
        </tr></thead><tbody><tr>
          <td scope="row">1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>15</td>
          <td>16</td>
          <td>17</td>
        </tr><tr>
          <td scope="row">18</td>
          <td>19</td>
          <td>20</td>
          <td>21</td>
          <td>22</td>
          <td>23</td>
          <td>24</td>
        </tr><tr>
          <td scope="row">25</td>
          <td>26</td>
          <td>27</td>
          <td>28</td>
          <td>29</td>
          <td>30</td>
          <td>31</td>
</tr></tbody></table>
</div>
<p>
      There are no dates between October 4 and October 15. This
      discontinuity is called the
      <span class="firstterm">cutover</span>. Any dates before
      the cutover are Julian, and any dates following the cutover are
      Gregorian. Dates during a cutover are nonexistent.
    </p><p>
      A calendar applied to dates when it was not actually in use is
      called <span class="firstterm">proleptic</span>. Thus, if
      we assume there was never a cutover and Gregorian rules always
      rule, we have a proleptic Gregorian calendar. This is what is used
      by MySQL, as is required by standard SQL. For this reason, dates
      prior to the cutover stored as MySQL
      <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> or
      <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> values must be adjusted to
      compensate for the difference. It is important to realize that the
      cutover did not occur at the same time in all countries, and that
      the later it happened, the more days were lost. For example, in
      Great Britain, it took place in 1752, when Wednesday September 2
      was followed by Thursday September 14. Russia remained on the
      Julian calendar until 1918, losing 13 days in the process, and
      what is popularly referred to as its <span class="quote">“<span class="quote">October
      Revolution</span>”</span> occurred in November according to the Gregorian
      calendar.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="fulltext-search"></a>12.9 Full-Text Search Functions</h2>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#fulltext-natural-language">12.9.1 Natural Language Full-Text Searches</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-boolean">12.9.2 Boolean Full-Text Searches</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-query-expansion">12.9.3 Full-Text Searches with Query Expansion</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-stopwords">12.9.4 Full-Text Stopwords</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-restrictions">12.9.5 Full-Text Restrictions</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-fine-tuning">12.9.6 Fine-Tuning MySQL Full-Text Search</a></span></dt><dt><span class="section"><a href="functions.html#full-text-adding-collation">12.9.7 Adding a Collation for Full-Text Indexing</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-search-ngram">12.9.8 ngram Full-Text Parser</a></span></dt><dt><span class="section"><a href="functions.html#fulltext-search-mecab">12.9.9 MeCab Full-Text Parser Plugin</a></span></dt></dl>
</div>
<a class="indexterm" name="idm46444327437936"></a><a class="indexterm" name="idm46444327436448"></a><a class="indexterm" name="idm46444327435376"></a><a class="indexterm" name="idm46444327434304"></a><p><a name="function_match"></a>
      <a class="link" href="functions.html#function_match"><code class="literal">MATCH
      (<em class="replaceable"><code>col1</code></em>,<em class="replaceable"><code>col2</code></em>,...)
      AGAINST (<em class="replaceable"><code>expr</code></em>
      [<em class="replaceable"><code>search_modifier</code></em>])</code></a>
    </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>search_modifier:</code></em>
  {
       IN NATURAL LANGUAGE MODE
     | IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
     | IN BOOLEAN MODE
     | WITH QUERY EXPANSION
  }
</pre><p>
      MySQL has support for full-text indexing and searching:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          A full-text index in MySQL is an index of type
          <code class="literal">FULLTEXT</code>.
        </p></li><li class="listitem"><p>
          Full-text indexes can be used only with
          <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a> or
          <a class="link" href="storage-engines.html#myisam-storage-engine" title="16.2 The MyISAM Storage Engine"><code class="literal">MyISAM</code></a> tables, and can be created
          only for <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a>,
          <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>, or
          <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">TEXT</code></a> columns.
        </p></li><li class="listitem"><p>
          MySQL provides a built-in full-text ngram parser that supports
          Chinese, Japanese, and Korean (CJK), and an installable MeCab
          full-text parser plugin for Japanese. Parsing differences are
          outlined in <a class="xref" href="functions.html#fulltext-search-ngram" title="12.9.8 ngram Full-Text Parser">Section 12.9.8, “ngram Full-Text Parser”</a>, and
          <a class="xref" href="functions.html#fulltext-search-mecab" title="12.9.9 MeCab Full-Text Parser Plugin">Section 12.9.9, “MeCab Full-Text Parser Plugin”</a>.
        </p></li><li class="listitem"><p>
          A <code class="literal">FULLTEXT</code> index definition can be given in
          the <a class="link" href="sql-statements.html#create-table" title="13.1.20 CREATE TABLE Statement"><code class="literal">CREATE TABLE</code></a> statement when
          a table is created, or added later using
          <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a> or
          <a class="link" href="sql-statements.html#create-index" title="13.1.15 CREATE INDEX Statement"><code class="literal">CREATE INDEX</code></a>.
        </p></li><li class="listitem"><p>
          For large data sets, it is much faster to load your data into
          a table that has no <code class="literal">FULLTEXT</code> index and then
          create the index after that, than to load data into a table
          that has an existing <code class="literal">FULLTEXT</code> index.
</p></li></ul>
</div>
<p>
      Full-text searching is performed using
      <a class="link" href="functions.html#function_match"><code class="literal">MATCH() ... AGAINST</code></a> syntax.
      <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> takes a comma-separated
      list that names the columns to be searched.
      <code class="literal">AGAINST</code> takes a string to search for, and an
      optional modifier that indicates what type of search to perform.
      The search string must be a string value that is constant during
      query evaluation. This rules out, for example, a table column
      because that can differ for each row.
    </p><p>
      There are three types of full-text searches:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          A natural language search interprets the search string as a
          phrase in natural human language (a phrase in free text).
          There are no special operators, with the exception of double
          quote (") characters. The stopword list applies. For more
          information about stopword lists, see
          <a class="xref" href="functions.html#fulltext-stopwords" title="12.9.4 Full-Text Stopwords">Section 12.9.4, “Full-Text Stopwords”</a>.
        </p><p>
          Full-text searches are natural language searches if the
          <code class="literal">IN NATURAL LANGUAGE MODE</code> modifier is given
          or if no modifier is given. For more information, see
          <a class="xref" href="functions.html#fulltext-natural-language" title="12.9.1 Natural Language Full-Text Searches">Section 12.9.1, “Natural Language Full-Text Searches”</a>.
        </p></li><li class="listitem"><p>
          A boolean search interprets the search string using the rules
          of a special query language. The string contains the words to
          search for. It can also contain operators that specify
          requirements such that a word must be present or absent in
          matching rows, or that it should be weighted higher or lower
          than usual. Certain common words (stopwords) are omitted from
          the search index and do not match if present in the search
          string. The <code class="literal">IN BOOLEAN MODE</code> modifier
          specifies a boolean search. For more information, see
          <a class="xref" href="functions.html#fulltext-boolean" title="12.9.2 Boolean Full-Text Searches">Section 12.9.2, “Boolean Full-Text Searches”</a>.
        </p></li><li class="listitem"><p>
          A query expansion search is a modification of a natural
          language search. The search string is used to perform a
          natural language search. Then words from the most relevant
          rows returned by the search are added to the search string and
          the search is done again. The query returns the rows from the
          second search. The <code class="literal">IN NATURAL LANGUAGE MODE WITH
          QUERY EXPANSION</code> or <code class="literal">WITH QUERY
          EXPANSION</code> modifier specifies a query expansion
          search. For more information, see
          <a class="xref" href="functions.html#fulltext-query-expansion" title="12.9.3 Full-Text Searches with Query Expansion">Section 12.9.3, “Full-Text Searches with Query Expansion”</a>.
</p></li></ul>
</div>
<p>
      For information about <code class="literal">FULLTEXT</code> query
      performance, see <a class="xref" href="optimization.html#column-indexes" title="8.3.5 Column Indexes">Section 8.3.5, “Column Indexes”</a>.
    </p><p>
      For more information about <code class="literal">InnoDB</code>
      <code class="literal">FULLTEXT</code> indexes, see
      <a class="xref" href="innodb-storage-engine.html#innodb-fulltext-index" title="15.6.2.4 InnoDB FULLTEXT Indexes">Section 15.6.2.4, “InnoDB FULLTEXT Indexes”</a>.
    </p><p>
      Constraints on full-text searching are listed in
      <a class="xref" href="functions.html#fulltext-restrictions" title="12.9.5 Full-Text Restrictions">Section 12.9.5, “Full-Text Restrictions”</a>.
    </p><p>
      The <a class="link" href="programs.html#myisam-ftdump" title="4.6.3 myisam_ftdump — Display Full-Text Index information"><span class="command"><strong>myisam_ftdump</strong></span></a> utility dumps the contents of
      a <code class="literal">MyISAM</code> full-text index. This may be helpful
      for debugging full-text queries. See
      <a class="xref" href="programs.html#myisam-ftdump" title="4.6.3 myisam_ftdump — Display Full-Text Index information">Section 4.6.3, “<span class="command"><strong>myisam_ftdump</strong></span> — Display Full-Text Index information”</a>.
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-natural-language"></a>12.9.1 Natural Language Full-Text Searches</h3>
</div>
</div>
</div>
<p>
        By default or with the <code class="literal">IN NATURAL LANGUAGE
        MODE</code> modifier, the
        <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> function performs a
        natural language search for a string against a
        <span class="firstterm">text collection</span>. A
        collection is a set of one or more columns included in a
        <code class="literal">FULLTEXT</code> index. The search string is given as
        the argument to <code class="literal">AGAINST()</code>. For each row in
        the table, <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> returns a
        relevance value; that is, a similarity measure between the
        search string and the text in that row in the columns named in
        the <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> list.
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE articles (</code></strong>
          <strong class="userinput"><code>id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,</code></strong>
          <strong class="userinput"><code>title VARCHAR(200),</code></strong>
          <strong class="userinput"><code>body TEXT,</code></strong>
          <strong class="userinput"><code>FULLTEXT (title,body)</code></strong>
        <strong class="userinput"><code>) ENGINE=InnoDB;</code></strong>
Query OK, 0 rows affected (0.08 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO articles (title,body) VALUES</code></strong>
        <strong class="userinput"><code>('MySQL Tutorial','DBMS stands for DataBase ...'),</code></strong>
        <strong class="userinput"><code>('How To Use MySQL Well','After you went through a ...'),</code></strong>
        <strong class="userinput"><code>('Optimizing MySQL','In this tutorial we will show ...'),</code></strong>
        <strong class="userinput"><code>('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),</code></strong>
        <strong class="userinput"><code>('MySQL vs. YourSQL','In the following database comparison ...'),</code></strong>
        <strong class="userinput"><code>('MySQL Security','When configured properly, MySQL ...');</code></strong>
Query OK, 6 rows affected (0.01 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT * FROM articles</code></strong>
        <strong class="userinput"><code>WHERE MATCH (title,body)</code></strong>
        <strong class="userinput"><code>AGAINST ('database' IN NATURAL LANGUAGE MODE);</code></strong>
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)
</pre><p>
        By default, the search is performed in case-insensitive fashion.
        To perform a case-sensitive full-text search, use a
        case-sensitive or binary collation for the indexed columns. For
        example, a column that uses the <code class="literal">utf8mb4</code>
        character set of can be assigned a collation of
        <code class="literal">utf8mb4_0900_as_cs</code> or
        <code class="literal">utf8mb4_bin</code> to make it case-sensitive for
        full-text searches.
      </p><p>
        When <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> is used in a
        <code class="literal">WHERE</code> clause, as in the example shown
        earlier, the rows returned are automatically sorted with the
        highest relevance first. Relevance values are nonnegative
        floating-point numbers. Zero relevance means no similarity.
        Relevance is computed based on the number of words in the row
        (document), the number of unique words in the row, the total
        number of words in the collection, and the number of rows that
        contain a particular word.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          The term <span class="quote">“<span class="quote">document</span>”</span> may be used interchangeably
          with the term <span class="quote">“<span class="quote">row</span>”</span>, and both terms refer to the
          indexed part of the row. The term <span class="quote">“<span class="quote">collection</span>”</span>
          refers to the indexed columns and encompasses all rows.
</p>
</div>
<p>
        To simply count matches, you could use a query like this:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COUNT(*) FROM articles</code></strong>
    <strong class="userinput"><code>WHERE MATCH (title,body)</code></strong>
    <strong class="userinput"><code>AGAINST ('database' IN NATURAL LANGUAGE MODE);</code></strong>
+----------+
| COUNT(*) |
+----------+
|        2 |
+----------+
1 row in set (0.00 sec)
</pre><p>
        You might find it quicker to rewrite the query as follows:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    <strong class="userinput"><code>COUNT(IF(MATCH (title,body) AGAINST ('database' IN NATURAL LANGUAGE MODE), 1, NULL))</code></strong>
    <strong class="userinput"><code>AS count</code></strong>
    <strong class="userinput"><code>FROM articles;</code></strong>
+-------+
| count |
+-------+
|     2 |
+-------+
1 row in set (0.03 sec)
</pre><p>
        The first query does some extra work (sorting the results by
        relevance) but also can use an index lookup based on the
        <code class="literal">WHERE</code> clause. The index lookup might make the
        first query faster if the search matches few rows. The second
        query performs a full table scan, which might be faster than the
        index lookup if the search term was present in most rows.
      </p><p>
        For natural-language full-text searches, the columns named in
        the <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> function must be the
        same columns included in some <code class="literal">FULLTEXT</code> index
        in your table. For the preceding query, note that the columns
        named in the <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> function
        (<code class="literal">title</code> and <code class="literal">body</code>) are the
        same as those named in the definition of the
        <code class="literal">article</code> table's <code class="literal">FULLTEXT</code>
        index. To search the <code class="literal">title</code> or
        <code class="literal">body</code> separately, you would create separate
        <code class="literal">FULLTEXT</code> indexes for each column.
      </p><p>
        You can also perform a boolean search or a search with query
        expansion. These search types are described in
        <a class="xref" href="functions.html#fulltext-boolean" title="12.9.2 Boolean Full-Text Searches">Section 12.9.2, “Boolean Full-Text Searches”</a>, and
        <a class="xref" href="functions.html#fulltext-query-expansion" title="12.9.3 Full-Text Searches with Query Expansion">Section 12.9.3, “Full-Text Searches with Query Expansion”</a>.
      </p><p>
        A full-text search that uses an index can name columns only from
        a single table in the <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a>
        clause because an index cannot span multiple tables. For
        <code class="literal">MyISAM</code> tables, a boolean search can be done
        in the absence of an index (albeit more slowly), in which case
        it is possible to name columns from multiple tables.
      </p><p>
        The preceding example is a basic illustration that shows how to
        use the <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> function where
        rows are returned in order of decreasing relevance. The next
        example shows how to retrieve the relevance values explicitly.
        Returned rows are not ordered because the
        <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement includes neither
        <code class="literal">WHERE</code> nor <code class="literal">ORDER BY</code>
        clauses:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT id, MATCH (title,body)</code></strong>
    <strong class="userinput"><code>AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) AS score</code></strong>
    <strong class="userinput"><code>FROM articles;</code></strong>
+----+---------------------+
| id | score               |
+----+---------------------+
|  1 | 0.22764469683170319 |
|  2 |                   0 |
|  3 | 0.22764469683170319 |
|  4 |                   0 |
|  5 |                   0 |
|  6 |                   0 |
+----+---------------------+
6 rows in set (0.00 sec)
</pre><p>
        The following example is more complex. The query returns the
        relevance values and it also sorts the rows in order of
        decreasing relevance. To achieve this result, specify
        <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> twice: once in the
        <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> list and once in the
        <code class="literal">WHERE</code> clause. This causes no additional
        overhead, because the MySQL optimizer notices that the two
        <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> calls are identical and
        invokes the full-text search code only once.
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT id, body, MATCH (title,body) AGAINST</code></strong>
    <strong class="userinput"><code>('Security implications of running MySQL as root'</code></strong>
    <strong class="userinput"><code>IN NATURAL LANGUAGE MODE) AS score</code></strong>
    <strong class="userinput"><code>FROM articles WHERE MATCH (title,body) AGAINST</code></strong>
    <strong class="userinput"><code>('Security implications of running MySQL as root'</code></strong>
    <strong class="userinput"><code>IN NATURAL LANGUAGE MODE);</code></strong>
+----+-------------------------------------+-----------------+
| id | body                                | score           |
+----+-------------------------------------+-----------------+
|  4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |
|  6 | When configured properly, MySQL ... | 1.3114095926285 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)
</pre><p>
        A phrase that is enclosed within double quote
        (<code class="literal">"</code>) characters matches only rows that contain
        the phrase <span class="emphasis"><em>literally, as it was typed</em></span>. The
        full-text engine splits the phrase into words and performs a
        search in the <code class="literal">FULLTEXT</code> index for the words.
        Nonword characters need not be matched exactly: Phrase searching
        requires only that matches contain exactly the same words as the
        phrase and in the same order. For example, <code class="literal">"test
        phrase"</code> matches <code class="literal">"test, phrase"</code>. If
        the phrase contains no words that are in the index, the result
        is empty. For example, if all words are either stopwords or
        shorter than the minimum length of indexed words, the result is
        empty.
      </p><p>
        The MySQL <code class="literal">FULLTEXT</code> implementation regards any
        sequence of true word characters (letters, digits, and
        underscores) as a word. That sequence may also contain
        apostrophes (<code class="literal">'</code>), but not more than one in a
        row. This means that <code class="literal">aaa'bbb</code> is regarded as
        one word, but <code class="literal">aaa''bbb</code> is regarded as two
        words. Apostrophes at the beginning or the end of a word are
        stripped by the <code class="literal">FULLTEXT</code> parser;
        <code class="literal">'aaa'bbb'</code> would be parsed as
        <code class="literal">aaa'bbb</code>.
      </p><p>
        The built-in <code class="literal">FULLTEXT</code> parser determines where
        words start and end by looking for certain delimiter characters;
        for example, <code class="literal"> </code> (space),
        <code class="literal">,</code> (comma), and <code class="literal">.</code> (period).
        If words are not separated by delimiters (as in, for example,
        Chinese), the built-in <code class="literal">FULLTEXT</code> parser cannot
        determine where a word begins or ends. To be able to add words
        or other indexed terms in such languages to a
        <code class="literal">FULLTEXT</code> index that uses the built-in
        <code class="literal">FULLTEXT</code> parser, you must preprocess them so
        that they are separated by some arbitrary delimiter.
        Alternatively, you can create <code class="literal">FULLTEXT</code>
        indexes using the ngram parser plugin (for Chinese, Japanese, or
        Korean) or the MeCab parser plugin (for Japanese).
      </p><p>
        It is possible to write a plugin that replaces the built-in
        full-text parser. For details, see <a class="xref" href="extending-mysql.html#plugin-api" title="29.2 The MySQL Plugin API">Section 29.2, “The MySQL Plugin API”</a>.
        For example parser plugin source code, see the
        <code class="filename">plugin/fulltext</code> directory of a MySQL source
        distribution.
      </p><p>
        Some words are ignored in full-text searches:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Any word that is too short is ignored. The default minimum
            length of words that are found by full-text searches is
            three characters for <code class="literal">InnoDB</code> search
            indexes, or four characters for <code class="literal">MyISAM</code>.
            You can control the cutoff by setting a configuration option
            before creating the index:
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>
            configuration option for <code class="literal">InnoDB</code> search
            indexes, or <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a>
            for <code class="literal">MyISAM</code>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
              This behavior does not apply to
              <code class="literal">FULLTEXT</code> indexes that use the ngram
              parser. For the ngram parser, token length is defined by
              the <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a>
              option.
</p>
</div>
</li><li class="listitem"><p>
            Words in the stopword list are ignored. A stopword is a word
            such as <span class="quote">“<span class="quote">the</span>”</span> or <span class="quote">“<span class="quote">some</span>”</span> that is so
            common that it is considered to have zero semantic value.
            There is a built-in stopword list, but it can be overridden
            by a user-defined list. The stopword lists and related
            configuration options are different for
            <code class="literal">InnoDB</code> search indexes and
            <code class="literal">MyISAM</code> ones. Stopword processing is
            controlled by the configuration options
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_enable_stopword"><code class="literal">innodb_ft_enable_stopword</code></a>,
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_server_stopword_table"><code class="literal">innodb_ft_server_stopword_table</code></a>,
            and
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_user_stopword_table"><code class="literal">innodb_ft_user_stopword_table</code></a>
            for <code class="literal">InnoDB</code> search indexes, and
            <a class="link" href="server-administration.html#sysvar_ft_stopword_file"><code class="literal">ft_stopword_file</code></a> for
            <code class="literal">MyISAM</code> ones.
</p></li></ul>
</div>
<p>
        See <a class="xref" href="functions.html#fulltext-stopwords" title="12.9.4 Full-Text Stopwords">Section 12.9.4, “Full-Text Stopwords”</a> to view default
        stopword lists and how to change them. The default minimum word
        length can be changed as described in
        <a class="xref" href="functions.html#fulltext-fine-tuning" title="12.9.6 Fine-Tuning MySQL Full-Text Search">Section 12.9.6, “Fine-Tuning MySQL Full-Text Search”</a>.
      </p><p>
        Every correct word in the collection and in the query is
        weighted according to its significance in the collection or
        query. Thus, a word that is present in many documents has a
        lower weight, because it has lower semantic value in this
        particular collection. Conversely, if the word is rare, it
        receives a higher weight. The weights of the words are combined
        to compute the relevance of the row. This technique works best
        with large collections.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
MyISAM Limitation
</div>
<p>
          For very small tables, word distribution does not adequately
          reflect their semantic value, and this model may sometimes
          produce bizarre results for search indexes on
          <code class="literal">MyISAM</code> tables. For example, although the
          word <span class="quote">“<span class="quote">MySQL</span>”</span> is present in every row of the
          <code class="literal">articles</code> table shown earlier, a search for
          the word in a <code class="literal">MyISAM</code> search index produces
          no results:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM articles</code></strong>
    <strong class="userinput"><code>WHERE MATCH (title,body)</code></strong>
    <strong class="userinput"><code>AGAINST ('MySQL' IN NATURAL LANGUAGE MODE);</code></strong>
Empty set (0.00 sec)
</pre><p>
          The search result is empty because the word
          <span class="quote">“<span class="quote">MySQL</span>”</span> is present in at least 50% of the rows,
          and so is effectively treated as a stopword. This filtering
          technique is more suitable for large data sets, where you
          might not want the result set to return every second row from
          a 1GB table, than for small data sets where it might cause
          poor results for popular terms.
        </p><p>
          The 50% threshold can surprise you when you first try
          full-text searching to see how it works, and makes
          <code class="literal">InnoDB</code> tables more suited to
          experimentation with full-text searches. If you create a
          <code class="literal">MyISAM</code> table and insert only one or two
          rows of text into it, every word in the text occurs in at
          least 50% of the rows. As a result, no search returns any
          results until the table contains more rows. Users who need to
          bypass the 50% limitation can build search indexes on
          <code class="literal">InnoDB</code> tables, or use the boolean search
          mode explained in <a class="xref" href="functions.html#fulltext-boolean" title="12.9.2 Boolean Full-Text Searches">Section 12.9.2, “Boolean Full-Text Searches”</a>.
</p>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-boolean"></a>12.9.2 Boolean Full-Text Searches</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444327253808"></a><a class="indexterm" name="idm46444327252768"></a><p>
        MySQL can perform boolean full-text searches using the
        <code class="literal">IN BOOLEAN MODE</code> modifier. With this modifier,
        certain characters have special meaning at the beginning or end
        of words in the search string. In the following query, the
        <code class="literal">+</code> and <code class="literal">-</code> operators indicate
        that a word must be present or absent, respectively, for a match
        to occur. Thus, the query retrieves all the rows that contain
        the word <span class="quote">“<span class="quote">MySQL</span>”</span> but that do
        <span class="emphasis"><em>not</em></span> contain the word
        <span class="quote">“<span class="quote">YourSQL</span>”</span>:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM articles WHERE MATCH (title,body)</code></strong>
    <strong class="userinput"><code>AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);</code></strong>
+----+-----------------------+-------------------------------------+
| id | title                 | body                                |
+----+-----------------------+-------------------------------------+
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Well | After you went through a ...        |
|  3 | Optimizing MySQL      | In this tutorial we will show ...   |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ... |
|  6 | MySQL Security        | When configured properly, MySQL ... |
+----+-----------------------+-------------------------------------+
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          In implementing this feature, MySQL uses what is sometimes
          referred to as <span class="firstterm">implied Boolean
          logic</span>, in which
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
              <code class="literal">+</code> stands for <code class="literal">AND</code>
            </p></li><li class="listitem"><p>
              <code class="literal">-</code> stands for <code class="literal">NOT</code>
            </p></li><li class="listitem"><p>
              [<span class="emphasis"><em>no operator</em></span>] implies
              <code class="literal">OR</code>
</p></li></ul>
</div>

</div>
<p>
        Boolean full-text searches have these characteristics:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            They do not automatically sort rows in order of decreasing
            relevance.
          </p></li><li class="listitem"><p>
            <code class="literal">InnoDB</code> tables require a
            <code class="literal">FULLTEXT</code> index on all columns of the
            <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> expression to perform
            boolean queries. Boolean queries against a
            <code class="literal">MyISAM</code> search index can work even without
            a <code class="literal">FULLTEXT</code> index, although a search
            executed in this fashion would be quite slow.
          </p></li><li class="listitem"><p>
            The minimum and maximum word length full-text parameters
            apply to <code class="literal">FULLTEXT</code> indexes created using
            the built-in <code class="literal">FULLTEXT</code> parser and MeCab
            parser plugin.
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>
            and
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_max_token_size"><code class="literal">innodb_ft_max_token_size</code></a>
            are used for <code class="literal">InnoDB</code> search indexes.
            <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a> and
            <a class="link" href="server-administration.html#sysvar_ft_max_word_len"><code class="literal">ft_max_word_len</code></a> are used
            for <code class="literal">MyISAM</code> search indexes.
          </p><p>
            Minimum and maximum word length full-text parameters do not
            apply to <code class="literal">FULLTEXT</code> indexes created using
            the ngram parser. ngram token size is defined by the
            <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> option.
          </p></li><li class="listitem"><p>
            The stopword list applies, controlled by
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_enable_stopword"><code class="literal">innodb_ft_enable_stopword</code></a>,
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_server_stopword_table"><code class="literal">innodb_ft_server_stopword_table</code></a>,
            and
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_user_stopword_table"><code class="literal">innodb_ft_user_stopword_table</code></a>
            for <code class="literal">InnoDB</code> search indexes, and
            <a class="link" href="server-administration.html#sysvar_ft_stopword_file"><code class="literal">ft_stopword_file</code></a> for
            <code class="literal">MyISAM</code> ones.
          </p></li><li class="listitem"><p>
            <code class="literal">InnoDB</code> full-text search does not support
            the use of multiple operators on a single search word, as in
            this example: <code class="literal">'++apple'</code>. Use of multiple
            operators on a single search word returns a syntax error to
            standard out. MyISAM full-text search will successfully
            process the same search ignoring all operators except for
            the operator immediately adjacent to the search word.
          </p></li><li class="listitem"><p>
            <code class="literal">InnoDB</code> full-text search only supports
            leading plus or minus signs. For example,
            <code class="literal">InnoDB</code> supports
            <code class="literal">'+apple'</code> but does not support
            <code class="literal">'apple+'</code>. Specifying a trailing plus or
            minus sign causes <code class="literal">InnoDB</code> to report a
            syntax error.
          </p></li><li class="listitem"><p>
            <code class="literal">InnoDB</code> full-text search does not support
            the use of a leading plus sign with wildcard
            (<code class="literal">'+*'</code>), a plus and minus sign combination
            (<code class="literal">'+-'</code>), or leading a plus and minus sign
            combination (<code class="literal">'+-apple'</code>). These invalid
            queries return a syntax error.
          </p></li><li class="listitem"><p>
            <code class="literal">InnoDB</code> full-text search does not support
            the use of the <code class="literal">@</code> symbol in boolean
            full-text searches. The <code class="literal">@</code> symbol is
            reserved for use by the <code class="literal">@distance</code>
            proximity search operator.
          </p></li><li class="listitem"><p>
            They do not use the 50% threshold that applies to
            <code class="literal">MyISAM</code> search indexes.
</p></li></ul>
</div>
<p>
        The boolean full-text search capability supports the following
        operators:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <code class="literal">+</code>
          </p><p>
            A leading or trailing plus sign indicates that this word
            <span class="emphasis"><em>must</em></span> be present in each row that is
            returned. <code class="literal">InnoDB</code> only supports leading
            plus signs.
          </p></li><li class="listitem"><p>
            <code class="literal">-</code>
          </p><p>
            A leading or trailing minus sign indicates that this word
            must <span class="emphasis"><em>not</em></span> be present in any of the rows
            that are returned. <code class="literal">InnoDB</code> only supports
            leading minus signs.
          </p><p>
            Note: The <code class="literal">-</code> operator acts only to exclude
            rows that are otherwise matched by other search terms. Thus,
            a boolean-mode search that contains only terms preceded by
            <code class="literal">-</code> returns an empty result. It does not
            return <span class="quote">“<span class="quote">all rows except those containing any of the
            excluded terms.</span>”</span>
          </p></li><li class="listitem"><p>
            (no operator)
          </p><p>
            By default (when neither <code class="literal">+</code> nor
            <code class="literal">-</code> is specified), the word is optional,
            but the rows that contain it are rated higher. This mimics
            the behavior of <a class="link" href="functions.html#function_match"><code class="literal">MATCH() ...
            AGAINST()</code></a> without the <code class="literal">IN BOOLEAN
            MODE</code> modifier.
          </p></li><li class="listitem"><p>
            <code class="literal">@<em class="replaceable"><code>distance</code></em></code>
          </p><p>
            This operator works on <code class="literal">InnoDB</code> tables
            only. It tests whether two or more words all start within a
            specified distance from each other, measured in words.
            Specify the search words within a double-quoted string
            immediately before the
            <code class="literal">@<em class="replaceable"><code>distance</code></em></code>
            operator, for example, <code class="literal">MATCH(col1) AGAINST('"word1
            word2 word3" @8' IN BOOLEAN MODE)</code>
          </p></li><li class="listitem"><p>
            <code class="literal">&gt; &lt;</code>
          </p><p>
            These two operators are used to change a word's contribution
            to the relevance value that is assigned to a row. The
            <code class="literal">&gt;</code> operator increases the contribution
            and the <code class="literal">&lt;</code> operator decreases it. See
            the example following this list.
          </p></li><li class="listitem"><p>
            <code class="literal">( )</code>
          </p><p>
            Parentheses group words into subexpressions. Parenthesized
            groups can be nested.
          </p></li><li class="listitem"><p>
            <code class="literal">~</code>
          </p><p>
            A leading tilde acts as a negation operator, causing the
            word's contribution to the row's relevance to be negative.
            This is useful for marking <span class="quote">“<span class="quote">noise</span>”</span> words. A row
            containing such a word is rated lower than others, but is
            not excluded altogether, as it would be with the
            <code class="literal">-</code> operator.
          </p></li><li class="listitem"><p>
            <code class="literal">*</code>
          </p><p>
            The asterisk serves as the truncation (or wildcard)
            operator. Unlike the other operators, it is
            <span class="emphasis"><em>appended</em></span> to the word to be affected.
            Words match if they begin with the word preceding the
            <code class="literal">*</code> operator.
          </p><p>
            If a word is specified with the truncation operator, it is
            not stripped from a boolean query, even if it is too short
            or a stopword. Whether a word is too short is determined
            from the
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>
            setting for <code class="literal">InnoDB</code> tables, or
            <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a> for
            <code class="literal">MyISAM</code> tables. These options are not
            applicable to <code class="literal">FULLTEXT</code> indexes that use
            the ngram parser.
          </p><p>
            The wildcarded word is considered as a prefix that must be
            present at the start of one or more words. If the minimum
            word length is 4, a search for
            <code class="literal">'+<em class="replaceable"><code>word</code></em> +the*'</code>
            could return fewer rows than a search for
            <code class="literal">'+<em class="replaceable"><code>word</code></em> +the'</code>,
            because the second query ignores the too-short search term
            <code class="literal">the</code>.
          </p></li><li class="listitem"><p>
            <code class="literal">"</code>
          </p><p>
            A phrase that is enclosed within double quote
            (<code class="literal">"</code>) characters matches only rows that
            contain the phrase <span class="emphasis"><em>literally, as it was
            typed</em></span>. The full-text engine splits the phrase
            into words and performs a search in the
            <code class="literal">FULLTEXT</code> index for the words. Nonword
            characters need not be matched exactly: Phrase searching
            requires only that matches contain exactly the same words as
            the phrase and in the same order. For example,
            <code class="literal">"test phrase"</code> matches <code class="literal">"test,
            phrase"</code>.
          </p><p>
            If the phrase contains no words that are in the index, the
            result is empty. The words might not be in the index because
            of a combination of factors: if they do not exist in the
            text, are stopwords, or are shorter than the minimum length
            of indexed words.
</p></li></ul>
</div>
<p>
        The following examples demonstrate some search strings that use
        boolean full-text operators:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <code class="literal">'apple banana'</code>
          </p><p>
            Find rows that contain at least one of the two words.
          </p></li><li class="listitem"><p>
            <code class="literal">'+apple +juice'</code>
          </p><p>
            Find rows that contain both words.
          </p></li><li class="listitem"><p>
            <code class="literal">'+apple macintosh'</code>
          </p><p>
            Find rows that contain the word <span class="quote">“<span class="quote">apple</span>”</span>, but
            rank rows higher if they also contain
            <span class="quote">“<span class="quote">macintosh</span>”</span>.
          </p></li><li class="listitem"><p>
            <code class="literal">'+apple -macintosh'</code>
          </p><p>
            Find rows that contain the word <span class="quote">“<span class="quote">apple</span>”</span> but not
            <span class="quote">“<span class="quote">macintosh</span>”</span>.
          </p></li><li class="listitem"><p>
            <code class="literal">'+apple ~macintosh'</code>
          </p><p>
            Find rows that contain the word <span class="quote">“<span class="quote">apple</span>”</span>, but if
            the row also contains the word <span class="quote">“<span class="quote">macintosh</span>”</span>,
            rate it lower than if row does not. This is
            <span class="quote">“<span class="quote">softer</span>”</span> than a search for <code class="literal">'+apple
            -macintosh'</code>, for which the presence of
            <span class="quote">“<span class="quote">macintosh</span>”</span> causes the row not to be returned
            at all.
          </p></li><li class="listitem"><p>
            <code class="literal">'+apple +(&gt;turnover &lt;strudel)'</code>
          </p><p>
            Find rows that contain the words <span class="quote">“<span class="quote">apple</span>”</span> and
            <span class="quote">“<span class="quote">turnover</span>”</span>, or <span class="quote">“<span class="quote">apple</span>”</span> and
            <span class="quote">“<span class="quote">strudel</span>”</span> (in any order), but rank <span class="quote">“<span class="quote">apple
            turnover</span>”</span> higher than <span class="quote">“<span class="quote">apple strudel</span>”</span>.
          </p></li><li class="listitem"><p>
            <code class="literal">'apple*'</code>
          </p><p>
            Find rows that contain words such as <span class="quote">“<span class="quote">apple</span>”</span>,
            <span class="quote">“<span class="quote">apples</span>”</span>, <span class="quote">“<span class="quote">applesauce</span>”</span>, or
            <span class="quote">“<span class="quote">applet</span>”</span>.
          </p></li><li class="listitem"><p>
            <code class="literal">'"some words"'</code>
          </p><p>
            Find rows that contain the exact phrase <span class="quote">“<span class="quote">some
            words</span>”</span> (for example, rows that contain <span class="quote">“<span class="quote">some
            words of wisdom</span>”</span> but not <span class="quote">“<span class="quote">some noise
            words</span>”</span>). Note that the <code class="literal">"</code>
            characters that enclose the phrase are operator characters
            that delimit the phrase. They are not the quotation marks
            that enclose the search string itself.
</p></li></ul>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-boolean-innodb-relevancy-ranking"></a>Relevancy Rankings for InnoDB Boolean Mode Search</h4>

</div>

</div>

</div>
<p>
          <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a> full-text search is
          modeled on the
          <a class="ulink" href="http://sphinxsearch.com/" target="_top">Sphinx</a> full-text
          search engine, and the algorithms used are based on
          <a class="ulink" href="http://en.wikipedia.org/wiki/Okapi_BM25" target="_top">BM25</a>
          and
          <a class="ulink" href="http://en.wikipedia.org/wiki/TF-IDF" target="_top">TF-IDF</a>
          ranking algorithms. For these reasons, relevancy rankings for
          <code class="literal">InnoDB</code> boolean full-text search may differ
          from <a class="link" href="storage-engines.html#myisam-storage-engine" title="16.2 The MyISAM Storage Engine"><code class="literal">MyISAM</code></a> relevancy rankings.
        </p><p>
          <code class="literal">InnoDB</code> uses a variation of the <span class="quote">“<span class="quote">term
          frequency-inverse document frequency</span>”</span>
          (<code class="literal">TF-IDF</code>) weighting system to rank a
          document's relevance for a given full-text search query. The
          <code class="literal">TF-IDF</code> weighting is based on how frequently
          a word appears in a document, offset by how frequently the
          word appears in all documents in the collection. In other
          words, the more frequently a word appears in a document, and
          the less frequently the word appears in the document
          collection, the higher the document is ranked.
</p>
<h5><a name="idm46444327106784"></a>How Relevancy Ranking is Calculated</h5>
<p>
          The term frequency (<code class="literal">TF</code>) value is the number
          of times that a word appears in a document. The inverse
          document frequency (<code class="literal">IDF</code>) value of a word is
          calculated using the following formula, where
          <code class="literal">total_records</code> is the number of records in
          the collection, and <code class="literal">matching_records</code> is the
          number of records that the search term appears in.
        </p><pre data-lang="simple" class="programlisting">${IDF} = log10( ${total_records} / ${matching_records} )  </pre><p>
          When a document contains a word multiple times, the IDF value
          is multiplied by the TF value:
        </p><pre data-lang="simple" class="programlisting">${TF} * ${IDF}</pre><p>
          Using the <code class="literal">TF</code> and <code class="literal">IDF</code>
          values, the relevancy ranking for a document is calculated
          using this formula:
        </p><pre data-lang="simple" class="programlisting">${rank} = ${TF} * ${IDF} * ${IDF}</pre><p>
          The formula is demonstrated in the following examples.
</p>
<h5><a name="idm46444327096608"></a>Relevancy Ranking for a Single Word Search</h5>
<p>
          This example demonstrates the relevancy ranking calculation
          for a single-word search.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
) ENGINE=InnoDB;
Query OK, 0 rows affected (1.04 sec)

mysql&gt; INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','This database tutorial ...'),
("How To Use MySQL",'After you went through a ...'),
('Optimizing Your Database','In this database tutorial ...'),
('MySQL vs. YourSQL','When comparing databases ...'),
('MySQL Security','When configured properly, MySQL ...'),
('Database, Database, Database','database database database'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL Full-Text Indexes', 'MySQL fulltext indexes use a ..');
Query OK, 8 rows affected (0.06 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql&gt; SELECT id, title, body, MATCH (title,body)  AGAINST ('database' IN BOOLEAN MODE)
AS score FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+---------------------+
| id | title                        | body                                | score               |
+----+------------------------------+-------------------------------------+---------------------+
|  6 | Database, Database, Database | database database database          |  1.0886961221694946 |
|  3 | Optimizing Your Database     | In this database tutorial ...       | 0.36289870738983154 |
|  1 | MySQL Tutorial               | This database tutorial ...          | 0.18144935369491577 |
|  2 | How To Use MySQL             | After you went through a ...        |                   0 |
|  4 | MySQL vs. YourSQL            | When comparing databases ...        |                   0 |
|  5 | MySQL Security               | When configured properly, MySQL ... |                   0 |
|  7 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... |                   0 |
|  8 | MySQL Full-Text Indexes      | MySQL fulltext indexes use a ..     |                   0 |
+----+------------------------------+-------------------------------------+---------------------+
8 rows in set (0.00 sec)</pre><p>
          There are 8 records in total, with 3 that match the
          <span class="quote">“<span class="quote">database</span>”</span> search term. The first record
          (<code class="literal">id 6</code>) contains the search term 6 times and
          has a relevancy ranking of
          <code class="literal">1.0886961221694946</code>. This ranking value is
          calculated using a <code class="literal">TF</code> value of 6 (the
          <span class="quote">“<span class="quote">database</span>”</span> search term appears 6 times in record
          <code class="literal">id 6</code>) and an <code class="literal">IDF</code> value
          of 0.42596873216370745, which is calculated as follows (where
          8 is the total number of records and 3 is the number of
          records that the search term appears in):
        </p><pre data-lang="simple" class="programlisting">${IDF} = log10( 8 / 3 ) = 0.42596873216370745</pre><p>
          The <code class="literal">TF</code> and <code class="literal">IDF</code> values
          are then entered into the ranking formula:
        </p><pre data-lang="simple" class="programlisting">${rank} = ${TF} * ${IDF} * ${IDF}</pre><p>
          Performing the calculation in the MySQL command-line client
          returns a ranking value of 1.088696164686938.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; SELECT 6*log10(8/3)*log10(8/3);
+-------------------------+
| 6*log10(8/3)*log10(8/3) |
+-------------------------+
|       1.088696164686938 |
+-------------------------+
1 row in set (0.00 sec)</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            You may notice a slight difference in the ranking values
            returned by the <code class="literal">SELECT ... MATCH ...
            AGAINST</code> statement and the MySQL command-line
            client (<code class="literal">1.0886961221694946</code> versus
            <code class="literal">1.088696164686938</code>). The difference is due
            to how the casts between integers and floats/doubles are
            performed internally by <code class="literal">InnoDB</code> (along
            with related precision and rounding decisions), and how they
            are performed elsewhere, such as in the MySQL command-line
            client or other types of calculators.
</p>
</div>
<h5><a name="idm46444327074864"></a>Relevancy Ranking for a Multiple Word Search</h5>
<p>
          This example demonstrates the relevancy ranking calculation
          for a multiple-word full-text search based on the
          <code class="literal">articles</code> table and data used in the
          previous example.
        </p><p>
          If you search on more than one word, the relevancy ranking
          value is a sum of the relevancy ranking value for each word,
          as shown in this formula:
        </p><pre data-lang="simple" class="programlisting">${rank} = ${TF} * ${IDF} * ${IDF} + ${TF} * ${IDF} * ${IDF}</pre><p>
          Performing a search on two terms ('mysql tutorial') returns
          the following results:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; SELECT id, title, body, MATCH (title,body)  AGAINST ('mysql tutorial' IN BOOLEAN MODE)
    AS score FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+----------------------+
| id | title                        | body                                | score                |
+----+------------------------------+-------------------------------------+----------------------+
|  1 | MySQL Tutorial               | This database tutorial ...          |   0.7405621409416199 |
|  3 | Optimizing Your Database     | In this database tutorial ...       |   0.3624762296676636 |
|  5 | MySQL Security               | When configured properly, MySQL ... | 0.031219376251101494 |
|  8 | MySQL Full-Text Indexes      | MySQL fulltext indexes use a ..     | 0.031219376251101494 |
|  2 | How To Use MySQL             | After you went through a ...        | 0.015609688125550747 |
|  4 | MySQL vs. YourSQL            | When comparing databases ...        | 0.015609688125550747 |
|  7 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... | 0.015609688125550747 |
|  6 | Database, Database, Database | database database database          |                    0 |
+----+------------------------------+-------------------------------------+----------------------+
8 rows in set (0.00 sec)</pre><p>
          In the first record (<code class="literal">id 8</code>), 'mysql' appears
          once and 'tutorial' appears twice. There are six matching
          records for 'mysql' and two matching records for 'tutorial'.
          The MySQL command-line client returns the expected ranking
          value when inserting these values into the ranking formula for
          a multiple word search:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; SELECT (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2));
+-------------------------------------------------------+
| (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2)) |
+-------------------------------------------------------+
|                                    0.7405621541938003 |
+-------------------------------------------------------+
1 row in set (0.00 sec)</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The slight difference in the ranking values returned by the
            <code class="literal">SELECT ... MATCH ... AGAINST</code> statement
            and the MySQL command-line client is explained in the
            preceding example.
</p>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-query-expansion"></a>12.9.3 Full-Text Searches with Query Expansion</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444327060112"></a><a class="indexterm" name="idm46444327059040"></a><p>
        Full-text search supports query expansion (and in particular,
        its variant <span class="quote">“<span class="quote">blind query expansion</span>”</span>). This is
        generally useful when a search phrase is too short, which often
        means that the user is relying on implied knowledge that the
        full-text search engine lacks. For example, a user searching for
        <span class="quote">“<span class="quote">database</span>”</span> may really mean that
        <span class="quote">“<span class="quote">MySQL</span>”</span>, <span class="quote">“<span class="quote">Oracle</span>”</span>, <span class="quote">“<span class="quote">DB2</span>”</span>,
        and <span class="quote">“<span class="quote">RDBMS</span>”</span> all are phrases that should match
        <span class="quote">“<span class="quote">databases</span>”</span> and should be returned, too. This is
        implied knowledge.
      </p><p>
        Blind query expansion (also known as automatic relevance
        feedback) is enabled by adding <code class="literal">WITH QUERY
        EXPANSION</code> or <code class="literal">IN NATURAL LANGUAGE MODE WITH
        QUERY EXPANSION</code> following the search phrase. It works
        by performing the search twice, where the search phrase for the
        second search is the original search phrase concatenated with
        the few most highly relevant documents from the first search.
        Thus, if one of these documents contains the word
        <span class="quote">“<span class="quote">databases</span>”</span> and the word <span class="quote">“<span class="quote">MySQL</span>”</span>, the
        second search finds the documents that contain the word
        <span class="quote">“<span class="quote">MySQL</span>”</span> even if they do not contain the word
        <span class="quote">“<span class="quote">database</span>”</span>. The following example shows this
        difference:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM articles</code></strong>
    <strong class="userinput"><code>WHERE MATCH (title,body)</code></strong>
    <strong class="userinput"><code>AGAINST ('database' IN NATURAL LANGUAGE MODE);</code></strong>
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT * FROM articles</code></strong>
    <strong class="userinput"><code>WHERE MATCH (title,body)</code></strong>
    <strong class="userinput"><code>AGAINST ('database' WITH QUERY EXPANSION);</code></strong>
+----+-----------------------+------------------------------------------+
| id | title                 | body                                     |
+----+-----------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL     | In the following database comparison ... |
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...             |
|  3 | Optimizing MySQL      | In this tutorial we will show ...        |
|  6 | MySQL Security        | When configured properly, MySQL ...      |
|  2 | How To Use MySQL Well | After you went through a ...             |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ...      |
+----+-----------------------+------------------------------------------+
6 rows in set (0.00 sec)
</pre><p>
        Another example could be searching for books by Georges Simenon
        about Maigret, when a user is not sure how to spell
        <span class="quote">“<span class="quote">Maigret</span>”</span>. A search for <span class="quote">“<span class="quote">Megre and the
        reluctant witnesses</span>”</span> finds only <span class="quote">“<span class="quote">Maigret and the
        Reluctant Witnesses</span>”</span> without query expansion. A search
        with query expansion finds all books with the word
        <span class="quote">“<span class="quote">Maigret</span>”</span> on the second pass.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          Because blind query expansion tends to increase noise
          significantly by returning nonrelevant documents, use it only
          when a search phrase is short.
</p>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-stopwords"></a>12.9.4 Full-Text Stopwords</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444327038304"></a><p>
        The stopword list is loaded and searched for full-text queries
        using the server character set and collation (the values of the
        <a class="link" href="server-administration.html#sysvar_character_set_server"><code class="literal">character_set_server</code></a> and
        <a class="link" href="server-administration.html#sysvar_collation_server"><code class="literal">collation_server</code></a> system
        variables). False hits or misses might occur for stopword
        lookups if the stopword file or columns used for full-text
        indexing or searches have a character set or collation different
        from <a class="link" href="server-administration.html#sysvar_character_set_server"><code class="literal">character_set_server</code></a> or
        <a class="link" href="server-administration.html#sysvar_collation_server"><code class="literal">collation_server</code></a>.
      </p><p>
        Case sensitivity of stopword lookups depends on the server
        collation. For example, lookups are case-insensitive if the
        collation is <code class="literal">utf8mb4_0900_ai_ci</code>, whereas
        lookups are case-sensitive if the collation is
        <code class="literal">utf8mb4_0900_as_cs</code> or
        <code class="literal">utf8mb4_bin</code>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><a class="xref" href="functions.html#fulltext-stopwords-stopwords-for-innodb-search-indexes" title="Stopwords for InnoDB Search Indexes">Stopwords for InnoDB Search Indexes</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#fulltext-stopwords-stopwords-for-myisam-search-indexes" title="Stopwords for MyISAM Search Indexes">Stopwords for MyISAM Search Indexes</a></p></li></ul>
</div>

<div class="simplesect">

<div class="titlepage">
<div>

<div class="simple">
<h4 class="title"><a name="fulltext-stopwords-stopwords-for-innodb-search-indexes"></a>Stopwords for InnoDB Search Indexes</h4>

</div>

</div>

</div>
<p>
          <code class="literal">InnoDB</code> has a relatively short list of
          default stopwords, because documents from technical, literary,
          and other sources often use short words as keywords or in
          significant phrases. For example, you might search for
          <span class="quote">“<span class="quote">to be or not to be</span>”</span> and expect to get a sensible
          result, rather than having all those words ignored.
        </p><p>
          To see the default <code class="literal">InnoDB</code> stopword list,
          query the
          <a class="link" href="information-schema.html#innodb-ft-default-stopword-table" title="25.46.15 The INFORMATION_SCHEMA INNODB_FT_DEFAULT_STOPWORD Table"><code class="literal">INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD</code></a>
          table.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD;
+-------+
| value |
+-------+
| a     |
| about |
| an    |
| are   |
| as    |
| at    |
| be    |
| by    |
| com   |
| de    |
| en    |
| for   |
| from  |
| how   |
| i     |
| in    |
| is    |
| it    |
| la    |
| of    |
| on    |
| or    |
| that  |
| the   |
| this  |
| to    |
| was   |
| what  |
| when  |
| where |
| who   |
| will  |
| with  |
| und   |
| the   |
| www   |
+-------+
36 rows in set (0.00 sec)</pre><p>
          To define your own stopword list for all
          <code class="literal">InnoDB</code> tables, define a table with the same
          structure as the
          <a class="link" href="information-schema.html#innodb-ft-default-stopword-table" title="25.46.15 The INFORMATION_SCHEMA INNODB_FT_DEFAULT_STOPWORD Table"><code class="literal">INNODB_FT_DEFAULT_STOPWORD</code></a> table,
          populate it with stopwords, and set the value of the
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_server_stopword_table"><code class="literal">innodb_ft_server_stopword_table</code></a>
          option to a value in the form
          <code class="literal"><em class="replaceable"><code>db_name</code></em>/<em class="replaceable"><code>table_name</code></em></code>
          before creating the full-text index. The stopword table must
          have a single <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a> column
          named <code class="literal">value</code>. The following example
          demonstrates creating and configuring a new global stopword
          table for <code class="literal">InnoDB</code>.
        </p><pre data-lang="sql" class="programlisting">-- Create a new stopword table

mysql&gt; CREATE TABLE my_stopwords(value VARCHAR(30)) ENGINE = INNODB;
Query OK, 0 rows affected (0.01 sec)

-- Insert stopwords (for simplicity, a single stopword is used in this example)

mysql&gt; INSERT INTO my_stopwords(value) VALUES ('Ishmael');
Query OK, 1 row affected (0.00 sec)

-- Create the table

mysql&gt; CREATE TABLE opening_lines (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500),
author VARCHAR(200),
title VARCHAR(200)
) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

-- Insert data into the table

mysql&gt; INSERT INTO opening_lines(opening_line,author,title) VALUES
('Call me Ishmael.','Herman Melville','Moby-Dick'),
('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),
('I am an invisible man.','Ralph Ellison','Invisible Man'),
('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),
('It was love at first sight.','Joseph Heller','Catch-22'),
('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),
('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),
('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');
Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0

-- Set the innodb_ft_server_stopword_table option to the new stopword table

mysql&gt; SET GLOBAL innodb_ft_server_stopword_table = 'test/my_stopwords';
Query OK, 0 rows affected (0.00 sec)

-- Create the full-text index (which rebuilds the table if no FTS_DOC_ID column is defined)

mysql&gt; CREATE FULLTEXT INDEX idx ON opening_lines(opening_line);
Query OK, 0 rows affected, 1 warning (1.17 sec)
Records: 0  Duplicates: 0  Warnings: 1</pre><p>
          Verify that the specified stopword ('Ishmael') does not appear
          by querying the words in
          <a class="link" href="information-schema.html#innodb-ft-index-table-table" title="25.46.18 The INFORMATION_SCHEMA INNODB_FT_INDEX_TABLE Table"><code class="literal">INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE</code></a>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            By default, words less than 3 characters in length or
            greater than 84 characters in length do not appear in an
            <code class="literal">InnoDB</code> full-text search index. Maximum
            and minimum word length values are configurable using the
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_max_token_size"><code class="literal">innodb_ft_max_token_size</code></a>
            and
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>
            variables. This default behavior does not apply to the ngram
            parser plugin. ngram token size is defined by the
            <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> option.
</p>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; SET GLOBAL innodb_ft_aux_table='test/opening_lines';
Query OK, 0 rows affected (0.00 sec)

mysql&gt; SELECT word FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE LIMIT 15;
+-----------+
| word      |
+-----------+
| across    |
| all       |
| burn      |
| buy       |
| call      |
| comes     |
| dalloway  |
| first     |
| flowers   |
| happened  |
| herself   |
| invisible |
| less      |
| love      |
| man       |
+-----------+
15 rows in set (0.00 sec)</pre><p>
          To create stopword lists on a table-by-table basis, create
          other stopword tables and use the
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_user_stopword_table"><code class="literal">innodb_ft_user_stopword_table</code></a>
          option to specify the stopword table that you want to use
          before you create the full-text index.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-stopwords-stopwords-for-myisam-search-indexes"></a>Stopwords for MyISAM Search Indexes</h4>

</div>

</div>

</div>
<p>
          The stopword file is loaded and searched using
          <code class="literal">latin1</code> if
          <code class="literal">character_set_server</code> is
          <code class="literal">ucs2</code>, <code class="literal">utf16</code>,
          <code class="literal">utf16le</code>, or <code class="literal">utf32</code>.
        </p><p>
          <a class="indexterm" name="idm46444326988096"></a>

          <a class="indexterm" name="idm46444326986608"></a>

          To override the default stopword list for MyISAM tables, set
          the <a class="link" href="server-administration.html#sysvar_ft_stopword_file"><code class="literal">ft_stopword_file</code></a> system
          variable. (See <a class="xref" href="server-administration.html#server-system-variables" title="5.1.8 Server System Variables">Section 5.1.8, “Server System Variables”</a>.) The
          variable value should be the path name of the file containing
          the stopword list, or the empty string to disable stopword
          filtering. The server looks for the file in the data directory
          unless an absolute path name is given to specify a different
          directory. After changing the value of this variable or the
          contents of the stopword file, restart the server and rebuild
          your <code class="literal">FULLTEXT</code> indexes.
        </p><p>
          The stopword list is free-form, separating stopwords with any
          nonalphanumeric character such as newline, space, or comma.
          Exceptions are the underscore character (<code class="literal">_</code>)
          and a single apostrophe (<code class="literal">'</code>) which are
          treated as part of a word. The character set of the stopword
          list is the server's default character set; see
          <a class="xref" href="charset.html#charset-server" title="10.3.2 Server Character Set and Collation">Section 10.3.2, “Server Character Set and Collation”</a>.
        </p><p>
          The following list shows the default stopwords for
          <code class="literal">MyISAM</code> search indexes. In a MySQL source
          distribution, you can find this list in the
          <code class="filename">storage/myisam/ft_static.c</code> file.
        </p><pre data-lang="simple" class="programlisting">a's           able          about         above         according
accordingly   across        actually      after         afterwards
again         against       ain't         all           allow
allows        almost        alone         along         already
also          although      always        am            among
amongst       an            and           another       any
anybody       anyhow        anyone        anything      anyway
anyways       anywhere      apart         appear        appreciate
appropriate   are           aren't        around        as
aside         ask           asking        associated    at
available     away          awfully       be            became
because       become        becomes       becoming      been
before        beforehand    behind        being         believe
below         beside        besides       best          better
between       beyond        both          brief         but
by            c'mon         c's           came          can
can't         cannot        cant          cause         causes
certain       certainly     changes       clearly       co
com           come          comes         concerning    consequently
consider      considering   contain       containing    contains
corresponding could         couldn't      course        currently
definitely    described     despite       did           didn't
different     do            does          doesn't       doing
don't         done          down          downwards     during
each          edu           eg            eight         either
else          elsewhere     enough        entirely      especially
et            etc           even          ever          every
everybody     everyone      everything    everywhere    ex
exactly       example       except        far           few
fifth         first         five          followed      following
follows       for           former        formerly      forth
four          from          further       furthermore   get
gets          getting       given         gives         go
goes          going         gone          got           gotten
greetings     had           hadn't        happens       hardly
has           hasn't        have          haven't       having
he            he's          hello         help          hence
her           here          here's        hereafter     hereby
herein        hereupon      hers          herself       hi
him           himself       his           hither        hopefully
how           howbeit       however       i'd           i'll
i'm           i've          ie            if            ignored
immediate     in            inasmuch      inc           indeed
indicate      indicated     indicates     inner         insofar
instead       into          inward        is            isn't
it            it'd          it'll         it's          its
itself        just          keep          keeps         kept
know          known         knows         last          lately
later         latter        latterly      least         less
lest          let           let's         like          liked
likely        little        look          looking       looks
ltd           mainly        many          may           maybe
me            mean          meanwhile     merely        might
more          moreover      most          mostly        much
must          my            myself        name          namely
nd            near          nearly        necessary     need
needs         neither       never         nevertheless  new
next          nine          no            nobody        non
none          noone         nor           normally      not
nothing       novel         now           nowhere       obviously
of            off           often         oh            ok
okay          old           on            once          one
ones          only          onto          or            other
others        otherwise     ought         our           ours
ourselves     out           outside       over          overall
own           particular    particularly  per           perhaps
placed        please        plus          possible      presumably
probably      provides      que           quite         qv
rather        rd            re            really        reasonably
regarding     regardless    regards       relatively    respectively
right         said          same          saw           say
saying        says          second        secondly      see
seeing        seem          seemed        seeming       seems
seen          self          selves        sensible      sent
serious       seriously     seven         several       shall
she           should        shouldn't     since         six
so            some          somebody      somehow       someone
something     sometime      sometimes     somewhat      somewhere
soon          sorry         specified     specify       specifying
still         sub           such          sup           sure
t's           take          taken         tell          tends
th            than          thank         thanks        thanx
that          that's        thats         the           their
theirs        them          themselves    then          thence
there         there's       thereafter    thereby       therefore
therein       theres        thereupon     these         they
they'd        they'll       they're       they've       think
third         this          thorough      thoroughly    those
though        three         through       throughout    thru
thus          to            together      too           took
toward        towards       tried         tries         truly
try           trying        twice         two           un
under         unfortunately unless        unlikely      until
unto          up            upon          us            use
used          useful        uses          using         usually
value         various       very          via           viz
vs            want          wants         was           wasn't
way           we            we'd          we'll         we're
we've         welcome       well          went          were
weren't       what          what's        whatever      when
whence        whenever      where         where's       whereafter
whereas       whereby       wherein       whereupon     wherever
whether       which         while         whither       who
who's         whoever       whole         whom          whose
why           will          willing       wish          with
within        without       won't         wonder        would
wouldn't      yes           yet           you           you'd
you'll        you're        you've        your          yours
yourself      yourselves    zero</pre>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-restrictions"></a>12.9.5 Full-Text Restrictions</h3>

</div>

</div>

</div>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Full-text searches are supported for
            <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a> and
            <a class="link" href="storage-engines.html#myisam-storage-engine" title="16.2 The MyISAM Storage Engine"><code class="literal">MyISAM</code></a> tables only.
          </p></li><li class="listitem"><p>
            Full-text searches are not supported for partitioned tables.
            See <a class="xref" href="partitioning.html#partitioning-limitations" title="23.6 Restrictions and Limitations on Partitioning">Section 23.6, “Restrictions and Limitations on Partitioning”</a>.
          </p></li><li class="listitem"><p>
            Full-text searches can be used with most multibyte character
            sets. The exception is that for Unicode, the
            <code class="literal">utf8</code> character set can be used, but not
            the <code class="literal">ucs2</code> character set. Although
            <code class="literal">FULLTEXT</code> indexes on
            <code class="literal">ucs2</code> columns cannot be used, you can
            perform <code class="literal">IN BOOLEAN MODE</code> searches on a
            <code class="literal">ucs2</code> column that has no such index.
          </p><p>
            The remarks for <code class="literal">utf8</code> also apply to
            <code class="literal">utf8mb4</code>, and the remarks for
            <code class="literal">ucs2</code> also apply to
            <code class="literal">utf16</code>, <code class="literal">utf16le</code>, and
            <code class="literal">utf32</code>.
          </p></li><li class="listitem"><p>
            Ideographic languages such as Chinese and Japanese do not
            have word delimiters. Therefore, the built-in full-text
            parser <span class="emphasis"><em>cannot determine where words begin and end
            in these and other such languages</em></span>.
          </p><p>
            A character-based ngram full-text parser that supports
            Chinese, Japanese, and Korean (CJK), and a word-based MeCab
            parser plugin that supports Japanese are provided for use
            with <code class="literal">InnoDB</code> and <code class="literal">MyISAM</code>
            tables.
          </p></li><li class="listitem"><p>
            Although the use of multiple character sets within a single
            table is supported, all columns in a
            <code class="literal">FULLTEXT</code> index must use the same
            character set and collation.
          </p></li><li class="listitem"><p>
            The <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> column list must
            match exactly the column list in some
            <code class="literal">FULLTEXT</code> index definition for the table,
            unless this <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a> is
            <code class="literal">IN BOOLEAN MODE</code> on a
            <code class="literal">MyISAM</code> table. For
            <code class="literal">MyISAM</code> tables, boolean-mode searches can
            be done on nonindexed columns, although they are likely to
            be slow.
          </p></li><li class="listitem"><p>
            The argument to <code class="literal">AGAINST()</code> must be a
            string value that is constant during query evaluation. This
            rules out, for example, a table column because that can
            differ for each row.
          </p></li><li class="listitem"><p>
            Index hints are more limited for <code class="literal">FULLTEXT</code>
            searches than for non-<code class="literal">FULLTEXT</code> searches.
            See <a class="xref" href="optimization.html#index-hints" title="8.9.4 Index Hints">Section 8.9.4, “Index Hints”</a>.
          </p></li><li class="listitem"><p>
            For <code class="literal">InnoDB</code>, all DML operations
            (<a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a>,
            <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a>,
            <a class="link" href="sql-statements.html#delete" title="13.2.2 DELETE Statement"><code class="literal">DELETE</code></a>) involving columns
            with full-text indexes are processed at transaction commit
            time. For example, for an <code class="literal">INSERT</code>
            operation, an inserted string is tokenized and decomposed
            into individual words. The individual words are then added
            to full-text index tables when the transaction is committed.
            As a result, full-text searches only return committed data.
          </p></li><li class="listitem"><p>
            The '%' character is not a supported wildcard character for
            full-text searches.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-fine-tuning"></a>12.9.6 Fine-Tuning MySQL Full-Text Search</h3>

</div>

</div>

</div>
<p>
        MySQL's full-text search capability has few user-tunable
        parameters. You can exert more control over full-text searching
        behavior if you have a MySQL source distribution because some
        changes require source code modifications. See
        <a class="xref" href="installing.html#source-installation" title="2.9 Installing MySQL from Source">Section 2.9, “Installing MySQL from Source”</a>.
      </p><p>
        Full-text search is carefully tuned for effectiveness. Modifying
        the default behavior in most cases can actually decrease
        effectiveness. <span class="emphasis"><em>Do not alter the MySQL sources unless
        you know what you are doing</em></span>.
      </p><p>
        Most full-text variables described in this section must be set
        at server startup time. A server restart is required to change
        them; they cannot be modified while the server is running.
      </p><p>
        Some variable changes require that you rebuild the
        <code class="literal">FULLTEXT</code> indexes in your tables. Instructions
        for doing so are given later in this section.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><a class="xref" href="functions.html#fulltext-word-length" title="Configuring Minimum and Maximum Word Length">Configuring Minimum and Maximum Word Length</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#fulltext-natural-language-threshold" title="Configuring the Natural Language Search Threshold">Configuring the Natural Language Search Threshold</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#fulltext-modify-boolean-operators" title="Modifying Boolean Full-Text Search Operators">Modifying Boolean Full-Text Search Operators</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#fulltext-modify-character-set" title="Character Set Modifications">Character Set Modifications</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#fulltext-rebuild-innodb-indexes" title="Rebuilding InnoDB Full-Text Indexes">Rebuilding InnoDB Full-Text Indexes</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#fulltext-optimize" title="Optimizing InnoDB Full-Text Indexes">Optimizing InnoDB Full-Text Indexes</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#fulltext-rebuild-myisam-indexes" title="Rebuilding MyISAM Full-Text Indexes">Rebuilding MyISAM Full-Text Indexes</a></p></li></ul>
</div>

<div class="simplesect">

<div class="titlepage">
<div>

<div class="simple">
<h4 class="title"><a name="fulltext-word-length"></a>Configuring Minimum and Maximum Word Length</h4>

</div>

</div>

</div>
<p>
          The minimum and maximum lengths of words to be indexed are
          defined by the
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a> and
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_max_token_size"><code class="literal">innodb_ft_max_token_size</code></a> for
          <code class="literal">InnoDB</code> search indexes, and
          <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a> and
          <a class="link" href="server-administration.html#sysvar_ft_max_word_len"><code class="literal">ft_max_word_len</code></a> for
          <code class="literal">MyISAM</code> ones.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            Minimum and maximum word length full-text parameters do not
            apply to <code class="literal">FULLTEXT</code> indexes created using
            the ngram parser. ngram token size is defined by the
            <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> option.
</p>
</div>
<p>
          After changing any of these options, rebuild your
          <code class="literal">FULLTEXT</code> indexes for the change to take
          effect. For example, to make two-character words searchable,
          you could put the following lines in an option file:
        </p><pre data-lang="ini" class="programlisting">[mysqld]
innodb_ft_min_token_size=2
ft_min_word_len=2</pre><p>
          Then restart the server and rebuild your
          <code class="literal">FULLTEXT</code> indexes. For
          <code class="literal">MyISAM</code> tables, note the remarks regarding
          <a class="link" href="programs.html#myisamchk" title="4.6.4 myisamchk — MyISAM Table-Maintenance Utility"><span class="command"><strong>myisamchk</strong></span></a> in the instructions that follow
          for rebuilding <code class="literal">MyISAM</code> full-text indexes.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-natural-language-threshold"></a>Configuring the Natural Language Search Threshold</h4>

</div>

</div>

</div>
<p>
          For <code class="literal">MyISAM</code> search indexes, the 50%
          threshold for natural language searches is determined by the
          particular weighting scheme chosen. To disable it, look for
          the following line in
          <code class="filename">storage/myisam/ftdefs.h</code>:
        </p><pre data-lang="c" class="programlisting">#define GWS_IN_USE GWS_PROB</pre><p>
          Change that line to this:
        </p><pre data-lang="c" class="programlisting">#define GWS_IN_USE GWS_FREQ</pre><p>
          Then recompile MySQL. There is no need to rebuild the indexes
          in this case.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            By making this change, you <span class="emphasis"><em>severely</em></span>
            decrease MySQL's ability to provide adequate relevance
            values for the <a class="link" href="functions.html#function_match"><code class="literal">MATCH()</code></a>
            function. If you really need to search for such common
            words, it would be better to search using <code class="literal">IN
            BOOLEAN MODE</code> instead, which does not observe the
            50% threshold.
</p>
</div>

</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-modify-boolean-operators"></a>Modifying Boolean Full-Text Search Operators</h4>

</div>

</div>

</div>
<p>
          To change the operators used for boolean full-text searches on
          <code class="literal">MyISAM</code> tables, set the
          <a class="link" href="server-administration.html#sysvar_ft_boolean_syntax"><code class="literal">ft_boolean_syntax</code></a> system
          variable. (<code class="literal">InnoDB</code> does not have an
          equivalent setting.) This variable can be changed while the
          server is running, but you must have privileges sufficient to
          set global system variables (see
          <a class="xref" href="server-administration.html#system-variable-privileges" title="5.1.9.1 System Variable Privileges">Section 5.1.9.1, “System Variable Privileges”</a>). No rebuilding
          of indexes is necessary in this case.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-modify-character-set"></a>Character Set Modifications</h4>

</div>

</div>

</div>
<p>
          For the built-in full-text parser, you can change the set of
          characters that are considered word characters in several
          ways, as described in the following list. After making the
          modification, rebuild the indexes for each table that contains
          any <code class="literal">FULLTEXT</code> indexes. Suppose that you want
          to treat the hyphen character ('-') as a word character. Use
          one of these methods:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
              Modify the MySQL source: In
              <code class="filename">storage/innobase/handler/ha_innodb.cc</code>
              (for <code class="literal">InnoDB</code>), or in
              <code class="filename">storage/myisam/ftdefs.h</code> (for
              <code class="literal">MyISAM</code>), see the
              <code class="literal">true_word_char()</code> and
              <code class="literal">misc_word_char()</code> macros. Add
              <code class="literal">'-'</code> to one of those macros and
              recompile MySQL.
            </p></li><li class="listitem"><p>
              Modify a character set file: This requires no
              recompilation. The <code class="literal">true_word_char()</code>
              macro uses a <span class="quote">“<span class="quote">character type</span>”</span> table to
              distinguish letters and numbers from other characters. .
              You can edit the contents of the
              <code class="literal">&lt;ctype&gt;&lt;map&gt;</code> array in one
              of the character set XML files to specify that
              <code class="literal">'-'</code> is a <span class="quote">“<span class="quote">letter.</span>”</span> Then
              use the given character set for your
              <code class="literal">FULLTEXT</code> indexes. For information about
              the <code class="literal">&lt;ctype&gt;&lt;map&gt;</code> array
              format, see <a class="xref" href="charset.html#character-arrays" title="10.13.1 Character Definition Arrays">Section 10.13.1, “Character Definition Arrays”</a>.
            </p></li><li class="listitem"><p>
              Add a new collation for the character set used by the
              indexed columns, and alter the columns to use that
              collation. For general information about adding
              collations, see <a class="xref" href="charset.html#adding-collation" title="10.14 Adding a Collation to a Character Set">Section 10.14, “Adding a Collation to a Character Set”</a>. For an
              example specific to full-text indexing, see
              <a class="xref" href="functions.html#full-text-adding-collation" title="12.9.7 Adding a Collation for Full-Text Indexing">Section 12.9.7, “Adding a Collation for Full-Text Indexing”</a>.
</p></li></ul>
</div>

</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-rebuild-innodb-indexes"></a>Rebuilding InnoDB Full-Text Indexes</h4>

</div>

</div>

</div>
<p>
          For the changes to take effect, <code class="literal">FULLTEXT</code>
          indexes must be rebuilt after modifying any of the following
          full-text index variables:
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>;
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_max_token_size"><code class="literal">innodb_ft_max_token_size</code></a>;
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_server_stopword_table"><code class="literal">innodb_ft_server_stopword_table</code></a>;
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_user_stopword_table"><code class="literal">innodb_ft_user_stopword_table</code></a>;
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_enable_stopword"><code class="literal">innodb_ft_enable_stopword</code></a>;
          <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a>. Modifying
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>,
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_max_token_size"><code class="literal">innodb_ft_max_token_size</code></a>, or
          <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> requires
          restarting the server.
        </p><p>
          To rebuild <code class="literal">FULLTEXT</code> indexes for an
          <code class="literal">InnoDB</code> table, use
          <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a> with the
          <code class="literal">DROP INDEX</code> and <code class="literal">ADD INDEX</code>
          options to drop and re-create each index.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-optimize"></a>Optimizing InnoDB Full-Text Indexes</h4>

</div>

</div>

</div>
<p>
          Running <a class="link" href="sql-statements.html#optimize-table" title="13.7.3.4 OPTIMIZE TABLE Statement"><code class="literal">OPTIMIZE TABLE</code></a> on a
          table with a full-text index rebuilds the full-text index,
          removing deleted Document IDs and consolidating multiple
          entries for the same word, where possible.
        </p><p>
          To optimize a full-text index, enable
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_optimize_fulltext_only"><code class="literal">innodb_optimize_fulltext_only</code></a>
          and run <code class="literal">OPTIMIZE TABLE</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; set GLOBAL innodb_optimize_fulltext_only=ON;
Query OK, 0 rows affected (0.01 sec)

mysql&gt; OPTIMIZE TABLE opening_lines;
+--------------------+----------+----------+----------+
| Table              | Op       | Msg_type | Msg_text |
+--------------------+----------+----------+----------+
| test.opening_lines | optimize | status   | OK       |
+--------------------+----------+----------+----------+
1 row in set (0.01 sec)    </pre><p>
          To avoid lengthy rebuild times for full-text indexes on large
          tables, you can use the
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_num_word_optimize"><code class="literal">innodb_ft_num_word_optimize</code></a>
          option to perform the optimization in stages. The
          <code class="literal">innodb_ft_num_word_optimize</code> option defines
          the number of words that are optimized each time
          <a class="link" href="sql-statements.html#optimize-table" title="13.7.3.4 OPTIMIZE TABLE Statement"><code class="literal">OPTIMIZE TABLE</code></a> is run. The
          default setting is 2000, which means that 2000 words are
          optimized each time <a class="link" href="sql-statements.html#optimize-table" title="13.7.3.4 OPTIMIZE TABLE Statement"><code class="literal">OPTIMIZE
          TABLE</code></a> is run. Subsequent
          <a class="link" href="sql-statements.html#optimize-table" title="13.7.3.4 OPTIMIZE TABLE Statement"><code class="literal">OPTIMIZE TABLE</code></a> operations
          continue from where the preceding
          <a class="link" href="sql-statements.html#optimize-table" title="13.7.3.4 OPTIMIZE TABLE Statement"><code class="literal">OPTIMIZE TABLE</code></a> operation ended.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="fulltext-rebuild-myisam-indexes"></a>Rebuilding MyISAM Full-Text Indexes</h4>

</div>

</div>

</div>
<p>
          If you modify full-text variables that affect indexing
          (<a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a>,
          <a class="link" href="server-administration.html#sysvar_ft_max_word_len"><code class="literal">ft_max_word_len</code></a>, or
          <a class="link" href="server-administration.html#sysvar_ft_stopword_file"><code class="literal">ft_stopword_file</code></a>), or if you
          change the stopword file itself, you must rebuild your
          <code class="literal">FULLTEXT</code> indexes after making the changes
          and restarting the server.
        </p><p>
          To rebuild the <code class="literal">FULLTEXT</code> indexes for a
          <code class="literal">MyISAM</code> table, it is sufficient to do a
          <code class="literal">QUICK</code> repair operation:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>REPAIR TABLE <em class="replaceable"><code>tbl_name</code></em> QUICK;</code></strong>
</pre><p>
          Alternatively, use <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a>
          as just described. In some cases, this may be faster than a
          repair operation.
        </p><p>
          Each table that contains any <code class="literal">FULLTEXT</code> index
          must be repaired as just shown. Otherwise, queries for the
          table may yield incorrect results, and modifications to the
          table will cause the server to see the table as corrupt and in
          need of repair.
        </p><p>
          If you use <a class="link" href="programs.html#myisamchk" title="4.6.4 myisamchk — MyISAM Table-Maintenance Utility"><span class="command"><strong>myisamchk</strong></span></a> to perform an
          operation that modifies <code class="literal">MyISAM </code> table
          indexes (such as repair or analyze), the
          <code class="literal">FULLTEXT</code> indexes are rebuilt using the
          <span class="emphasis"><em>default</em></span> full-text parameter values for
          minimum word length, maximum word length, and stopword file
          unless you specify otherwise. This can result in queries
          failing.
        </p><p>
          The problem occurs because these parameters are known only by
          the server. They are not stored in <code class="literal">MyISAM</code>
          index files. To avoid the problem if you have modified the
          minimum or maximum word length or stopword file values used by
          the server, specify the same
          <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a>,
          <a class="link" href="server-administration.html#sysvar_ft_max_word_len"><code class="literal">ft_max_word_len</code></a>, and
          <a class="link" href="server-administration.html#sysvar_ft_stopword_file"><code class="literal">ft_stopword_file</code></a> values for
          <a class="link" href="programs.html#myisamchk" title="4.6.4 myisamchk — MyISAM Table-Maintenance Utility"><span class="command"><strong>myisamchk</strong></span></a> that you use for
          <a class="link" href="programs.html#mysqld" title="4.3.1 mysqld — The MySQL Server"><span class="command"><strong>mysqld</strong></span></a>. For example, if you have set the
          minimum word length to 3, you can repair a table with
          <a class="link" href="programs.html#myisamchk" title="4.6.4 myisamchk — MyISAM Table-Maintenance Utility"><span class="command"><strong>myisamchk</strong></span></a> like this:
        </p><pre data-lang="terminal" class="programlisting">myisamchk --recover --ft_min_word_len=3 <em class="replaceable"><code>tbl_name</code></em>.MYI
</pre><p>
          To ensure that <a class="link" href="programs.html#myisamchk" title="4.6.4 myisamchk — MyISAM Table-Maintenance Utility"><span class="command"><strong>myisamchk</strong></span></a> and the server use
          the same values for full-text parameters, place each one in
          both the <code class="literal">[mysqld]</code> and
          <code class="literal">[myisamchk]</code> sections of an option file:
        </p><pre data-lang="ini" class="programlisting">[mysqld]
ft_min_word_len=3

[myisamchk]
ft_min_word_len=3</pre><p>
          An alternative to using <a class="link" href="programs.html#myisamchk" title="4.6.4 myisamchk — MyISAM Table-Maintenance Utility"><span class="command"><strong>myisamchk</strong></span></a> for
          <code class="literal">MyISAM</code> table index modification is to use
          the <a class="link" href="sql-statements.html#repair-table" title="13.7.3.5 REPAIR TABLE Statement"><code class="literal">REPAIR TABLE</code></a>,
          <a class="link" href="sql-statements.html#analyze-table" title="13.7.3.1 ANALYZE TABLE Statement"><code class="literal">ANALYZE TABLE</code></a>,
          <a class="link" href="sql-statements.html#optimize-table" title="13.7.3.4 OPTIMIZE TABLE Statement"><code class="literal">OPTIMIZE TABLE</code></a>, or
          <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a> statements. These
          statements are performed by the server, which knows the proper
          full-text parameter values to use.
</p>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="full-text-adding-collation"></a>12.9.7 Adding a Collation for Full-Text Indexing</h3>

</div>

</div>

</div>
<p>
        This section describes how to add a new collation for full-text
        searches using the built-in full-text parser. The sample
        collation is like <code class="literal">latin1_swedish_ci</code> but
        treats the <code class="literal">'-'</code> character as a letter rather
        than as a punctuation character so that it can be indexed as a
        word character. General information about adding collations is
        given in <a class="xref" href="charset.html#adding-collation" title="10.14 Adding a Collation to a Character Set">Section 10.14, “Adding a Collation to a Character Set”</a>; it is assumed that
        you have read it and are familiar with the files involved.
      </p><p>
        To add a collation for full-text indexing, use the following
        procedure. The instructions here add a collation for a simple
        character set, which as discussed in
        <a class="xref" href="charset.html#adding-collation" title="10.14 Adding a Collation to a Character Set">Section 10.14, “Adding a Collation to a Character Set”</a>, can be created using a
        configuration file that describes the character set properties.
        For a complex character set such as Unicode, create collations
        using C source files that describe the character set properties.
</p>
<div class="orderedlist">
<ol class="orderedlist" type="1"><li class="listitem"><p>
            Add a collation to the <code class="filename">Index.xml</code> file.
            The collation ID must be unused, so choose a value different
            from 1000 if that ID is already taken on your system.
          </p><pre data-lang="xml" class="programlisting">&lt;charset name="latin1"&gt;
...
&lt;collation name="latin1_fulltext_ci" id="1000"/&gt;
&lt;/charset&gt;</pre></li><li class="listitem"><p>
            Declare the sort order for the collation in the
            <code class="filename">latin1.xml</code> file. In this case, the
            order can be copied from
            <code class="literal">latin1_swedish_ci</code>:
          </p><pre data-lang="xml" class="programlisting">&lt;collation name="latin1_fulltext_ci"&gt;
&lt;map&gt;
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
&lt;/map&gt;
&lt;/collation&gt;</pre></li><li class="listitem"><p>
            Modify the <code class="literal">ctype</code> array in
            <code class="filename">latin1.xml</code>. Change the value
            corresponding to 0x2D (which is the code for the
            <code class="literal">'-'</code> character) from 10 (punctuation) to
            01 (uppercase letter). In the following array, this is the
            element in the fourth row down, third value from the end.
          </p><pre data-lang="xml" class="programlisting">&lt;ctype&gt;
&lt;map&gt;
00
20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
48 10 10 10 10 10 10 10 10 10 10 10 10 <em class="replaceable"><code>01</code></em> 10 10
84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
10 00 10 02 10 10 10 10 10 10 01 10 01 00 01 00
00 10 10 10 10 10 10 10 10 10 02 10 02 00 02 01
48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
&lt;/map&gt;
&lt;/ctype&gt;
</pre></li><li class="listitem"><p>
            Restart the server.
          </p></li><li class="listitem"><p>
            To employ the new collation, include it in the definition of
            columns that are to use it:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>DROP TABLE IF EXISTS t1;</code></strong>
Query OK, 0 rows affected (0.13 sec)

mysql&gt; <strong class="userinput"><code>CREATE TABLE t1 (</code></strong>
    <strong class="userinput"><code>a TEXT CHARACTER SET latin1 COLLATE latin1_fulltext_ci,</code></strong>
    <strong class="userinput"><code>FULLTEXT INDEX(a)</code></strong>
    <strong class="userinput"><code>) ENGINE=InnoDB;</code></strong>
Query OK, 0 rows affected (0.47 sec)
</pre></li><li class="listitem"><p>
            Test the collation to verify that hyphen is considered as a
            word character:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>INSERT INTO t1 VALUEs ('----'),('....'),('abcd');</code></strong>
Query OK, 3 rows affected (0.22 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT * FROM t1 WHERE MATCH a AGAINST ('----' IN BOOLEAN MODE);</code></strong>
+------+
| a    |
+------+
| ---- |
+------+
1 row in set (0.00 sec)
</pre></li></ol>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-search-ngram"></a>12.9.8 ngram Full-Text Parser</h3>

</div>

</div>

</div>
<p>
        The built-in MySQL full-text parser uses the white space between
        words as a delimiter to determine where words begin and end,
        which is a limitation when working with ideographic languages
        that do not use word delimiters. To address this limitation,
        MySQL provides an ngram full-text parser that supports Chinese,
        Japanese, and Korean (CJK). The ngram full-text parser is
        supported for use with <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a> and
        <a class="link" href="storage-engines.html#myisam-storage-engine" title="16.2 The MyISAM Storage Engine"><code class="literal">MyISAM</code></a>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          MySQL also provides a MeCab full-text parser plugin for
          Japanese, which tokenizes documents into meaningful words. For
          more information, see <a class="xref" href="functions.html#fulltext-search-mecab" title="12.9.9 MeCab Full-Text Parser Plugin">Section 12.9.9, “MeCab Full-Text Parser Plugin”</a>.
</p>
</div>
<p>
        An ngram is a contiguous sequence of
        <em class="replaceable"><code>n</code></em> characters from a given sequence of
        text. The ngram parser tokenizes a sequence of text into a
        contiguous sequence of <em class="replaceable"><code>n</code></em> characters.
        For example, you can tokenize <span class="quote">“<span class="quote">abcd</span>”</span> for different
        values of <em class="replaceable"><code>n</code></em> using the ngram full-text
        parser.
      </p><pre data-lang="simple" class="programlisting">n=1: 'a', 'b', 'c', 'd'
n=2: 'ab', 'bc', 'cd'
n=3: 'abc', 'bcd'
n=4: 'abcd'</pre><p>
        The ngram full-text parser is a built-in server plugin. As with
        other built-in server plugins, it is automatically loaded when
        the server is started.
      </p><p>
        The full-text search syntax described in
        <a class="xref" href="functions.html#fulltext-search" title="12.9 Full-Text Search Functions">Section 12.9, “Full-Text Search Functions”</a> applies to the ngram parser
        plugin. Differences in parsing behavior are described in this
        section. Full-text-related configuration options, except for
        minimum and maximum word length options
        (<a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>,
        <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_max_token_size"><code class="literal">innodb_ft_max_token_size</code></a>,
        <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a>,
        <a class="link" href="server-administration.html#sysvar_ft_max_word_len"><code class="literal">ft_max_word_len</code></a>) are also
        applicable.
</p>
<h4><a name="idm46444326736848"></a>Configuring ngram Token Size</h4>
<p>
        The ngram parser has a default ngram token size of 2 (bigram).
        For example, with a token size of 2, the ngram parser parses the
        string <span class="quote">“<span class="quote">abc def</span>”</span> into four tokens:
        <span class="quote">“<span class="quote">ab</span>”</span>, <span class="quote">“<span class="quote">bc</span>”</span>, <span class="quote">“<span class="quote">de</span>”</span> and
        <span class="quote">“<span class="quote">ef</span>”</span>.
      </p><p>
        ngram token size is configurable using the
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> configuration
        option, which has a minimum value of 1 and maximum value of 10.
      </p><p>
        Typically, <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> is
        set to the size of the largest token that you want to search
        for. If you only intend to search for single characters, set
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> to 1. A
        smaller token size produces a smaller full-text search index,
        and faster searches. If you need to search for words comprised
        of more than one character, set
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> accordingly.
        For example, <span class="quote">“<span class="quote">Happy Birthday</span>”</span> is
        <span class="quote">“<span class="quote"><span lang="zh-cn" class="phrase">生日快乐</span></span>”</span> in
        simplified Chinese, where
        <span class="quote">“<span class="quote"><span lang="zh-cn" class="phrase">生日</span></span>”</span> is
        <span class="quote">“<span class="quote">birthday</span>”</span>, and
        <span class="quote">“<span class="quote"><span lang="zh-cn" class="phrase">快乐</span></span>”</span> translates
        as <span class="quote">“<span class="quote">happy</span>”</span>. To search on two-character words such
        as these, set <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a>
        to a value of 2 or higher.
      </p><p>
        As a read-only variable,
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> may only be
        set as part of a startup string or in a configuration file:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Startup string:
          </p><pre data-lang="terminal" class="programlisting">mysqld --ngram_token_size=2</pre></li><li class="listitem"><p>
            Configuration file:
          </p><pre data-lang="ini" class="programlisting">[mysqld]
ngram_token_size=2</pre></li></ul>
</div>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<div class="admon-title">
Note
</div>
<p>
          The following minimum and maximum word length configuration
          options are ignored for <code class="literal">FULLTEXT</code> indexes
          that use the ngram parser:
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>,
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_max_token_size"><code class="literal">innodb_ft_max_token_size</code></a>,
          <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a>, and
          <a class="link" href="server-administration.html#sysvar_ft_max_word_len"><code class="literal">ft_max_word_len</code></a>.
</p>
</div>
<h4><a name="idm46444326709536"></a>Creating a FULLTEXT Index that Uses the ngram Parser</h4>
<p>
        To create a <code class="literal">FULLTEXT</code> index that uses the
        ngram parser, specify <code class="literal">WITH PARSER ngram</code> with
        <a class="link" href="sql-statements.html#create-table" title="13.1.20 CREATE TABLE Statement"><code class="literal">CREATE TABLE</code></a>,
        <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a>, or
        <a class="link" href="sql-statements.html#create-index" title="13.1.15 CREATE INDEX Statement"><code class="literal">CREATE INDEX</code></a>.
      </p><p>
        The following example demonstrates creating a table with an
        <code class="literal">ngram</code> <code class="literal">FULLTEXT</code> index,
        inserting sample data (Simplified Chinese text), and viewing
        tokenized data in the
        <a class="link" href="information-schema.html#innodb-ft-index-cache-table" title="25.46.17 The INFORMATION_SCHEMA INNODB_FT_INDEX_CACHE Table"><code class="literal">INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE</code></a>
        table.
      </p><pre data-lang="sql" class="programlisting">mysql&gt; USE test;

mysql&gt; CREATE TABLE articles (
      id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
      title VARCHAR(200),
      body TEXT,
      FULLTEXT (title,body) WITH PARSER ngram
    ) ENGINE=InnoDB CHARACTER SET utf8mb4;

mysql&gt; SET NAMES utf8mb4;

INSERT INTO articles (title,body) VALUES
    ('数据库管理','在本教程中我将向你展示如何管理数据库'),
    ('数据库应用开发','学习开发数据库应用程序');

mysql&gt; SET GLOBAL innodb_ft_aux_table="test/articles";

mysql&gt; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position;</pre><p>
        To add a <code class="literal">FULLTEXT</code> index to an existing table,
        you can use <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a> or
        <a class="link" href="sql-statements.html#create-index" title="13.1.15 CREATE INDEX Statement"><code class="literal">CREATE INDEX</code></a>. For example:
      </p><pre data-lang="sql" class="programlisting">CREATE TABLE articles (
      id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
      title VARCHAR(200),
      body TEXT
     ) ENGINE=InnoDB CHARACTER SET utf8;

ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) WITH PARSER ngram;

# Or:

CREATE FULLTEXT INDEX ft_index ON articles (title,body) WITH PARSER ngram;</pre>
<h4><a name="idm46444326692656"></a>ngram Parser Space Handling</h4>
<p>
        The ngram parser eliminates spaces when parsing. For example:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <span class="quote">“<span class="quote">ab cd</span>”</span> is parsed to <span class="quote">“<span class="quote">ab</span>”</span>,
            <span class="quote">“<span class="quote">cd</span>”</span>
          </p></li><li class="listitem"><p>
            <span class="quote">“<span class="quote">a bc</span>”</span> is parsed to <span class="quote">“<span class="quote">bc</span>”</span>
</p></li></ul>
</div>
<h4><a name="idm46444326687456"></a>ngram Parser Stopword Handling</h4>
<p>
        The built-in MySQL full-text parser compares words to entries in
        the stopword list. If a word is equal to an entry in the
        stopword list, the word is excluded from the index. For the
        ngram parser, stopword handling is performed differently.
        Instead of excluding tokens that are equal to entries in the
        stopword list, the ngram parser excludes tokens that
        <span class="emphasis"><em>contain</em></span> stopwords. For example, assuming
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size=2</code></a>, a document
        that contains <span class="quote">“<span class="quote">a,b</span>”</span> is parsed to <span class="quote">“<span class="quote">a,</span>”</span>
        and <span class="quote">“<span class="quote">,b</span>”</span>. If a comma (<span class="quote">“<span class="quote">,</span>”</span>) is defined
        as a stopword, both <span class="quote">“<span class="quote">a,</span>”</span> and <span class="quote">“<span class="quote">,b</span>”</span> are
        excluded from the index because they contain a comma.
      </p><p>
        By default, the ngram parser uses the default stopword list,
        which contains a list of English stopwords. For a stopword list
        applicable to Chinese, Japanese, or Korean, you must create your
        own. For information about creating a stopword list, see
        <a class="xref" href="functions.html#fulltext-stopwords" title="12.9.4 Full-Text Stopwords">Section 12.9.4, “Full-Text Stopwords”</a>.
      </p><p>
        Stopwords greater in length than
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size</code></a> are ignored.
</p>
<h4><a name="idm46444326678416"></a>ngram Parser Term Search</h4>
<p>
        For <span class="emphasis"><em>natural language mode</em></span> search, the
        search term is converted to a union of ngram terms. For example,
        the string <span class="quote">“<span class="quote">abc</span>”</span> (assuming
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size=2</code></a>) is
        converted to <span class="quote">“<span class="quote">ab bc</span>”</span>. Given two documents, one
        containing <span class="quote">“<span class="quote">ab</span>”</span> and the other containing
        <span class="quote">“<span class="quote">abc</span>”</span>, the search term <span class="quote">“<span class="quote">ab bc</span>”</span> matches
        both documents.
      </p><p>
        For <span class="emphasis"><em>boolean mode search</em></span>, the search term is
        converted to an ngram phrase search. For example, the string
        'abc' (assuming
        <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size=2</code></a>) is
        converted to '<span class="quote">“<span class="quote">ab bc</span>”</span>'. Given two documents, one
        containing 'ab' and the other containing 'abc', the search
        phrase '<span class="quote">“<span class="quote">ab bc</span>”</span>' only matches the document
        containing 'abc'.
</p>
<h4><a name="idm46444326670016"></a>ngram Parser Wildcard Search</h4>
<p>
        Because an ngram <code class="literal">FULLTEXT</code> index contains only
        ngrams, and does not contain information about the beginning of
        terms, wildcard searches may return unexpected results. The
        following behaviors apply to wildcard searches using ngram
        <code class="literal">FULLTEXT</code> search indexes:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If the prefix term of a wildcard search is shorter than
            ngram token size, the query returns all indexed rows that
            contain ngram tokens starting with the prefix term. For
            example, assuming
            <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size=2</code></a>, a
            search on <span class="quote">“<span class="quote">a*</span>”</span> returns all rows starting with
            <span class="quote">“<span class="quote">a</span>”</span>.
          </p></li><li class="listitem"><p>
            If the prefix term of a wildcard search is longer than ngram
            token size, the prefix term is converted to an ngram phrase
            and the wildcard operator is ignored. For example, assuming
            <a class="link" href="server-administration.html#sysvar_ngram_token_size"><code class="literal">ngram_token_size=2</code></a>, an
            <span class="quote">“<span class="quote">abc*</span>”</span> wildcard search is converted to
            <span class="quote">“<span class="quote">ab bc</span>”</span>.
</p></li></ul>
</div>
<h4><a name="idm46444326660496"></a>ngram Parser Phrase Search</h4>
<p>
        Phrase searches are converted to ngram phrase searches. For
        example, The search phrase <span class="quote">“<span class="quote">abc</span>”</span> is converted to
        <span class="quote">“<span class="quote">ab bc</span>”</span>, which returns documents containing
        <span class="quote">“<span class="quote">abc</span>”</span> and <span class="quote">“<span class="quote">ab bc</span>”</span>.
      </p><p>
        The search phrase <span class="quote">“<span class="quote">abc def</span>”</span> is converted to
        <span class="quote">“<span class="quote">ab bc de ef</span>”</span>, which returns documents containing
        <span class="quote">“<span class="quote">abc def</span>”</span> and <span class="quote">“<span class="quote">ab bc de ef</span>”</span>. A
        document that contains <span class="quote">“<span class="quote">abcdef</span>”</span> is not returned.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="fulltext-search-mecab"></a>12.9.9 MeCab Full-Text Parser Plugin</h3>

</div>

</div>

</div>
<p>
        The built-in MySQL full-text parser uses the white space between
        words as a delimiter to determine where words begin and end,
        which is a limitation when working with ideographic languages
        that do not use word delimiters. To address this limitation for
        Japanese, MySQL provides a MeCab full-text parser plugin. The
        MeCab full-text parser plugin is supported for use with
        <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a> and
        <a class="link" href="storage-engines.html#myisam-storage-engine" title="16.2 The MyISAM Storage Engine"><code class="literal">MyISAM</code></a>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          MySQL also provides an ngram full-text parser plugin that
          supports Japanese. For more information, see
          <a class="xref" href="functions.html#fulltext-search-ngram" title="12.9.8 ngram Full-Text Parser">Section 12.9.8, “ngram Full-Text Parser”</a>.
</p>
</div>
<p>
        The MeCab full-text parser plugin is a full-text parser plugin
        for Japanese that tokenizes a sequence of text into meaningful
        words. For example, MeCab tokenizes
        <span class="quote">“<span class="quote"><span lang="ja" class="phrase">データベース管理</span></span>”</span>
        (<span class="quote">“<span class="quote">Database Management</span>”</span>) into
        <span class="quote">“<span class="quote"><span lang="ja" class="phrase">データベース</span></span>”</span>
        (<span class="quote">“<span class="quote">Database</span>”</span>) and
        <span class="quote">“<span class="quote"><span lang="ja" class="phrase">管理</span></span>”</span>
        (<span class="quote">“<span class="quote">Management</span>”</span>). By comparison, the
        <a class="link" href="functions.html#fulltext-search-ngram" title="12.9.8 ngram Full-Text Parser">ngram</a> full-text
        parser tokenizes text into a contiguous sequence of
        <em class="replaceable"><code>n</code></em> characters, where
        <em class="replaceable"><code>n</code></em> represents a number between 1 and
        10.
      </p><p>
        In addition to tokenizing text into meaningful words, MeCab
        indexes are typically smaller than ngram indexes, and MeCab
        full-text searches are generally faster. One drawback is that it
        may take longer for the MeCab full-text parser to tokenize
        documents, compared to the ngram full-text parser.
      </p><p>
        The full-text search syntax described in
        <a class="xref" href="functions.html#fulltext-search" title="12.9 Full-Text Search Functions">Section 12.9, “Full-Text Search Functions”</a> applies to the MeCab parser
        plugin. Differences in parsing behavior are described in this
        section. Full-text related configuration options are also
        applicable.
      </p><p>
        For additional information about the MeCab parser, refer to the
        <a class="ulink" href="http://taku910.github.io/mecab/" target="_top">MeCab: Yet Another
        Part-of-Speech and Morphological Analyzer</a> project on
        Github.
</p>
<h4><a name="idm46444326639120"></a>Installing the MeCab Parser Plugin</h4>
<p>
        The MeCab parser plugin requires <code class="filename">mecab</code> and
        <code class="filename">mecab-ipadic</code>.
      </p><p>
        On supported Fedora, Debian and Ubuntu platforms (except Ubuntu
        12.04 where the system <code class="filename">mecab</code> version is too
        old), MySQL dynamically links to the system
        <code class="filename">mecab</code> installation if it is installed to
        the default location. On other supported Unix-like platforms,
        <code class="filename">libmecab.so</code> is statically linked in
        <code class="filename">libpluginmecab.so</code>, which is located in the
        MySQL plugin directory. <code class="filename">mecab-ipadic</code> is
        included in MySQL binaries and is located in
        <code class="filename"><em class="replaceable"><code>MYSQL_HOME</code></em>\lib\mecab</code>.
      </p><p>
        You can install <code class="filename">mecab</code> and
        <code class="filename">mecab-ipadic</code> using a native package
        management utility (on Fedora, Debian, and Ubuntu), or you can
        build <code class="filename">mecab</code> and
        <code class="filename">mecab-ipadic</code> from source. For information
        about installing <code class="filename">mecab</code> and
        <code class="filename">mecab-ipadic</code> using a native package
        management utility, see
        <a class="link" href="functions.html#install-mecab-binary" title="Installing MeCab From a Binary Distribution (Optional)">Installing MeCab From a
        Binary Distribution (Optional)</a>. If you want to build
        <code class="filename">mecab</code> and <code class="literal">mecab-ipadic</code>
        from source, see
        <a class="link" href="functions.html#build-mecab-from-source" title="Installing MeCab From Source (Optional)">Building MeCab From
        Source (Optional)</a>.
      </p><p>
        On Windows, <code class="filename">libmecab.dll</code> is found in the
        MySQL <code class="filename">bin</code> directory.
        <code class="filename">mecab-ipadic</code> is located in
        <code class="filename"><em class="replaceable"><code>MYSQL_HOME</code></em>/lib/mecab</code>.
      </p><p>
        To install and configure the MeCab parser plugin, perform the
        following steps:
</p>
<div class="orderedlist">
<ol class="orderedlist" type="1"><li class="listitem"><p>
            In the MySQL configuration file, set the
            <a class="link" href="server-administration.html#sysvar_mecab_rc_file"><code class="literal">mecab_rc_file</code></a> configuration
            option to the location of the <code class="literal">mecabrc</code>
            configuration file, which is the configuration file for
            MeCab. If you are using the MeCab package distributed with
            MySQL, the <code class="literal">mecabrc</code> file is located in
            <code class="filename">MYSQL_HOME/lib/mecab/etc/</code>.
          </p><pre data-lang="ini" class="programlisting">[mysqld]
loose-mecab-rc-file=MYSQL_HOME/lib/mecab/etc/mecabrc</pre><p>
            The <code class="literal">loose</code> prefix is an
            <a class="link" href="programs.html#option-modifiers" title="4.2.2.4 Program Option Modifiers">option modifier</a>. The
            <a class="link" href="server-administration.html#sysvar_mecab_rc_file"><code class="literal">mecab_rc_file</code></a> option is not
            recognized by MySQL until the MeCaB parser plugin is
            installed but it must be set before attempting to install
            the MeCaB parser plugin. The <code class="literal">loose</code> prefix
            allows you restart MySQL without encountering an error due
            to an unrecognized variable.
          </p><p>
            If you use your own MeCab installation, or build MeCab from
            source, the location of the <code class="filename">mecabrc</code>
            configuration file may differ.
          </p><p>
            For information about the MySQL configuration file and its
            location, see <a class="xref" href="programs.html#option-files" title="4.2.2.2 Using Option Files">Section 4.2.2.2, “Using Option Files”</a>.
          </p></li><li class="listitem"><p>
            Also in the MySQL configuration file, set the minimum token
            size to 1 or 2, which are the values recommended for use
            with the MeCab parser. For <code class="literal">InnoDB</code> tables,
            minimum token size is defined by the
            <a class="link" href="innodb-storage-engine.html#sysvar_innodb_ft_min_token_size"><code class="literal">innodb_ft_min_token_size</code></a>
            configuration option, which has a default value of 3. For
            <code class="literal">MyISAM</code> tables, minimum token size is
            defined by <a class="link" href="server-administration.html#sysvar_ft_min_word_len"><code class="literal">ft_min_word_len</code></a>,
            which has a default value of 4.
          </p><pre data-lang="ini" class="programlisting">[mysqld]
innodb_ft_min_token_size=1</pre></li><li class="listitem"><p>
            Modify the <code class="filename">mecabrc</code> configuration file
            to specify the dictionary you want to use. The
            <code class="filename">mecab-ipadic</code> package distributed with
            MySQL binaries includes three dictionaries
            (<code class="literal">ipadic_euc-jp</code>,
            <code class="literal">ipadic_sjis</code>, and
            <code class="literal">ipadic_utf-8</code>). The
            <code class="filename">mecabrc</code> configuration file packaged
            with MySQL contains and entry similar to the following:
          </p><pre data-lang="ini" class="programlisting">dicdir =  /path/to/mysql/lib/mecab/lib/mecab/dic/ipadic_euc-jp</pre><p>
            To use the <code class="filename">ipadic_utf-8</code> dictionary, for
            example, modify the entry as follows:
          </p><pre data-lang="ini" class="programlisting">dicdir=<em class="replaceable"><code>MYSQL_HOME</code></em>/lib/mecab/dic/ipadic_utf-8</pre><p>
            If you are using your own MeCab installation or have built
            MeCab from source, the default <code class="literal">dicdir</code>
            entry in the <code class="filename">mecabrc</code> file will differ,
            as will the dictionaries and their location.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
              After the MeCab parser plugin is installed, you can use
              the <a class="link" href="server-administration.html#statvar_mecab_charset"><code class="literal">mecab_charset</code></a> status
              variable to view the character set used with MeCab. The
              three MeCab dictionaries provided with the MySQL binary
              support the following character sets.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
                  The <code class="literal">ipadic_euc-jp</code> dictionary
                  supports the <code class="literal">ujis</code> and
                  <code class="literal">eucjpms</code> character sets.
                </p></li><li class="listitem"><p>
                  The <code class="literal">ipadic_sjis</code> dictionary supports
                  the <code class="literal">sjis</code> and
                  <code class="literal">cp932</code> character sets.
                </p></li><li class="listitem"><p>
                  The <code class="literal">ipadic_utf-8</code> dictionary
                  supports the <code class="literal">utf8</code> and
                  <code class="literal">utf8mb4</code> character sets.
</p></li></ul>
</div>
<p>
              <a class="link" href="server-administration.html#statvar_mecab_charset"><code class="literal">mecab_charset</code></a> only
              reports the first supported character set. For example,
              the <code class="literal">ipadic_utf-8</code> dictionary supports
              both <code class="literal">utf8</code> and
              <code class="literal">utf8mb4</code>.
              <a class="link" href="server-administration.html#statvar_mecab_charset"><code class="literal">mecab_charset</code></a> always
              reports <code class="literal">utf8</code> when this dictionary is in
              use.
</p>
</div>
</li><li class="listitem"><p>
            Restart MySQL.
          </p></li><li class="listitem"><p>
            Install the MeCab parser plugin:
          </p><p>
            The MeCab parser plugin is installed using
            <a class="link" href="sql-statements.html#install-plugin" title="13.7.4.4 INSTALL PLUGIN Statement"><code class="literal">INSTALL PLUGIN</code></a> syntax. The
            plugin name is <code class="filename">mecab</code>, and the shared
            library name is <code class="filename">libpluginmecab.so</code>. For
            additional information about installing plugins, see
            <a class="xref" href="server-administration.html#plugin-loading" title="5.6.1 Installing and Uninstalling Plugins">Section 5.6.1, “Installing and Uninstalling Plugins”</a>.
          </p><pre data-lang="sql" class="programlisting">INSTALL PLUGIN mecab SONAME 'libpluginmecab.so';</pre><p>
            Once installed, the MeCab parser plugin loads at every
            normal MySQL restart.
          </p></li><li class="listitem"><p>
            Verify that the MeCab parser plugin is loaded using the
            <a class="link" href="sql-statements.html#show-plugins" title="13.7.7.25 SHOW PLUGINS Statement"><code class="literal">SHOW PLUGINS</code></a> statement.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; SHOW PLUGINS;</pre><p>
            A <code class="literal">mecab</code> plugin should appear in the list
            of plugins.
</p></li></ol>
</div>
<h4><a name="idm46444326559584"></a>Creating a FULLTEXT Index that uses the MeCab Parser</h4>
<p>
        To create a <code class="literal">FULLTEXT</code> index that uses the
        mecab parser, specify <code class="literal">WITH PARSER ngram</code> with
        <a class="link" href="sql-statements.html#create-table" title="13.1.20 CREATE TABLE Statement"><code class="literal">CREATE TABLE</code></a>,
        <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a>, or
        <a class="link" href="sql-statements.html#create-index" title="13.1.15 CREATE INDEX Statement"><code class="literal">CREATE INDEX</code></a>.
      </p><p>
        This example demonstrates creating a table with a
        <code class="literal">mecab</code> <code class="literal">FULLTEXT</code> index,
        inserting sample data, and viewing tokenized data in the
        <a class="link" href="information-schema.html#innodb-ft-index-cache-table" title="25.46.17 The INFORMATION_SCHEMA INNODB_FT_INDEX_CACHE Table"><code class="literal">INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE</code></a>
        table:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; USE test;

mysql&gt; CREATE TABLE articles (
      id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
      title VARCHAR(200),
      body TEXT,
      FULLTEXT (title,body) WITH PARSER mecab
    ) ENGINE=InnoDB CHARACTER SET utf8;

mysql&gt; SET NAMES utf8;

mysql&gt; INSERT INTO articles (title,body) VALUES
    ('データベース管理','このチュートリアルでは、私はどのようにデータベースを管理する方法を紹介します'),
    ('データベースアプリケーション開発','データベースアプリケーションを開発することを学ぶ');

mysql&gt; SET GLOBAL innodb_ft_aux_table="test/articles";

mysql&gt; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position;</pre><p>
        To add a <code class="literal">FULLTEXT</code> index to an existing table,
        you can use <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a> or
        <a class="link" href="sql-statements.html#create-index" title="13.1.15 CREATE INDEX Statement"><code class="literal">CREATE INDEX</code></a>. For example:
      </p><pre data-lang="sql" class="programlisting">CREATE TABLE articles (
      id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
      title VARCHAR(200),
      body TEXT
     ) ENGINE=InnoDB CHARACTER SET utf8;

ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) WITH PARSER mecab;

# Or:

CREATE FULLTEXT INDEX ft_index ON articles (title,body) WITH PARSER mecab;</pre>
<h4><a name="idm46444326542528"></a>MeCab Parser Space Handling</h4>
<p>
        The MeCab parser uses spaces as separators in query strings. For
        example, the MeCab parser tokenizes
        <span lang="ja" class="phrase">データベース管理</span> as
        <span lang="ja" class="phrase">データベース</span> and
        <span lang="ja" class="phrase">管理</span>.
</p>
<h4><a name="idm46444326539200"></a>MeCab Parser Stopword Handling</h4>
<p>
        By default, the MeCab parser uses the default stopword list,
        which contains a short list of English stopwords. For a stopword
        list applicable to Japanese, you must create your own. For
        information about creating stopword lists, see
        <a class="xref" href="functions.html#fulltext-stopwords" title="12.9.4 Full-Text Stopwords">Section 12.9.4, “Full-Text Stopwords”</a>.
</p>
<h4><a name="idm46444326537136"></a>MeCab Parser Term Search</h4>
<p>
        For natural language mode search, the search term is converted
        to a union of tokens. For example,
        <span lang="ja" class="phrase">データベース管理</span> is converted
        to <span lang="ja" class="phrase">データベース 管理</span>.
      </p><pre data-lang="sql" class="programlisting">SELECT COUNT(*) FROM articles WHERE MATCH(title,body) AGAINST('データベース管理' IN NATURAL LANGUAGE MODE);</pre><p>
        For boolean mode search, the search term is converted to a
        search phrase. For example,
        <span lang="ja" class="phrase">データベース管理</span> is converted
        to <span lang="ja" class="phrase">データベース 管理</span>.
</p><pre data-lang="sql" class="programlisting">SELECT COUNT(*) FROM articles WHERE MATCH(title,body) AGAINST('データベース管理' IN BOOLEAN MODE);</pre>
<h4><a name="idm46444326530272"></a>MeCab Parser Wildcard Search</h4>
<p>
        Wildcard search terms are not tokenized. A search on
        <span lang="ja" class="phrase">データベース管理*</span> is
        performed on the prefix,
        <span lang="ja" class="phrase">データベース管理</span>.
</p><pre data-lang="sql" class="programlisting">SELECT COUNT(*) FROM articles WHERE MATCH(title,body) AGAINST('データベース*' IN BOOLEAN MODE);</pre>
<h4><a name="idm46444326526528"></a>MeCab Parser Phrase Search</h4>
<p>
        Phrases are tokenized. For example,
        <span lang="ja" class="phrase">データベース管理</span> is tokenized
        as <span lang="ja" class="phrase">データベース 管理</span>.
</p><pre data-lang="sql" class="programlisting">SELECT COUNT(*) FROM articles WHERE MATCH(title,body) AGAINST('"データベース管理"' IN BOOLEAN MODE);</pre>
<h4><a name="install-mecab-binary"></a>Installing MeCab From a Binary Distribution (Optional)</h4>
<p>
        This section describes how to install <code class="filename">mecab</code>
        and <code class="filename">mecab-ipadic</code> from a binary distribution
        using a native package management utility. For example, on
        Fedora, you can use Yum to perform the installation:
      </p><pre data-lang="terminal" class="programlisting">yum mecab-devel</pre><p>
        On Debian or Ubuntu, you can perform an APT installation:
      </p><pre data-lang="terminal" class="programlisting">apt-get install mecab
apt-get install mecab-ipadic</pre>
<h4><a name="build-mecab-from-source"></a>Installing MeCab From Source (Optional)</h4>
<p>
        If you want to build <code class="filename">mecab</code> and
        <code class="filename">mecab-ipadic</code> from source, basic
        installation steps are provided below. For additional
        information, refer to the MeCab documentation.
</p>
<div class="orderedlist">
<ol class="orderedlist" type="1"><li class="listitem"><p>
            Download the tar.gz packages for <code class="filename">mecab</code>
            and <code class="filename">mecab-ipadic</code> from
            <a class="ulink" href="http://taku910.github.io/mecab/#download" target="_top">http://taku910.github.io/mecab/#download</a>. As
            of February, 2016, the latest available packages are
            <code class="filename">mecab-0.996.tar.gz</code> and
            <code class="filename">mecab-ipadic-2.7.0-20070801.tar.gz</code>.
          </p></li><li class="listitem"><p>
            Install <code class="filename">mecab</code>:
          </p><pre data-lang="terminal" class="programlisting">tar zxfv mecab-0.996.tar
cd mecab-0.996
./configure
make
make check
su
make install</pre></li><li class="listitem"><p>
            Install <code class="filename">mecab-ipadic</code>:
          </p><pre data-lang="terminal" class="programlisting">tar zxfv mecab-ipadic-2.7.0-20070801.tar
cd mecab-ipadic-2.7.0-20070801
./configure
make
su
make install</pre></li><li class="listitem"><p>
            Compile MySQL using the
            <a class="link" href="installing.html#option_cmake_with_mecab"><code class="option">WITH_MECAB</code></a> CMake option. Set
            the <a class="link" href="installing.html#option_cmake_with_mecab"><code class="option">WITH_MECAB</code></a> option to
            <code class="literal">system</code> if you have installed
            <code class="filename">mecab</code> and
            <code class="filename">mecab-ipadic</code> to the default location.
          </p><pre data-lang="terminal" class="programlisting">-DWITH_MECAB=system</pre><p>
            If you defined a custom installation directory, set
            <a class="link" href="installing.html#option_cmake_with_mecab"><code class="option">WITH_MECAB</code></a> to the custom
            directory. For example:
</p><pre data-lang="terminal" class="programlisting">-DWITH_MECAB=/path/to/mecab</pre></li></ol>
</div>

</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="cast-functions"></a>12.10 Cast Functions and Operators</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444326493904"></a><a class="indexterm" name="idm46444326492864"></a><a class="indexterm" name="idm46444326491792"></a><a class="indexterm" name="idm46444326490304"></a><a class="indexterm" name="idm46444326489232"></a>
<div class="table">
<a name="idm46444326487744"></a><p class="title"><b>Table 12.14 Cast Functions and Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists cast functions and operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a></td>
<td>
      Cast a string to a binary string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a></td>
<td>
      Cast a value as a certain type
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a></td>
<td>
      Cast a value as a certain type
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      Cast functions and operators enable conversion of values from one
      data type to another.
    </p><p>
      <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> with a
      <code class="literal">USING</code> clause converts data between different
      character sets:
    </p><pre data-lang="sql" class="programlisting">CONVERT(<em class="replaceable"><code>expr</code></em> USING <em class="replaceable"><code>transcoding_name</code></em>)
</pre><p>
      In MySQL, transcoding names are the same as the corresponding
      character set names.
    </p><p>
      Examples:
    </p><pre data-lang="sql" class="programlisting">SELECT CONVERT('test' USING utf8mb4);
SELECT CONVERT(_latin1'Müller' USING utf8mb4);
INSERT INTO utf8mb4_table (utf8mb4_column)
    SELECT CONVERT(latin1_column USING utf8mb4) FROM latin1_table;</pre><p>
      To convert strings between different character sets, you can also
      use <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> without
      <code class="literal">USING</code>, or
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a>:
    </p><pre data-lang="sql" class="programlisting">CONVERT(<em class="replaceable"><code>string</code></em>, CHAR[(<em class="replaceable"><code>N</code></em>)] CHARACTER SET <em class="replaceable"><code>charset_name</code></em>)
CAST(<em class="replaceable"><code>string</code></em> AS CHAR[(<em class="replaceable"><code>N</code></em>)] CHARACTER SET <em class="replaceable"><code>charset_name</code></em>)
</pre><p>
      Examples:
    </p><pre data-lang="sql" class="programlisting">SELECT CONVERT('test', CHAR CHARACTER SET utf8mb4);
SELECT CAST('test' AS CHAR CHARACTER SET utf8mb4);</pre><p>
      If you specify <code class="literal">CHARACTER SET
      <em class="replaceable"><code>charset_name</code></em></code> as just shown,
      the character set and collation of the result are
      <em class="replaceable"><code>charset_name</code></em> and the default collation
      of <em class="replaceable"><code>charset_name</code></em>. If you omit
      <code class="literal">CHARACTER SET
      <em class="replaceable"><code>charset_name</code></em></code>, the character
      set and collation of the result are defined by the
      <a class="link" href="server-administration.html#sysvar_character_set_connection"><code class="literal">character_set_connection</code></a> and
      <a class="link" href="server-administration.html#sysvar_collation_connection"><code class="literal">collation_connection</code></a> system
      variables that determine the default connection character set and
      collation (see <a class="xref" href="charset.html#charset-connection" title="10.4 Connection Character Sets and Collations">Section 10.4, “Connection Character Sets and Collations”</a>).
    </p><p>
      A <code class="literal">COLLATE</code> clause is not permitted within a
      <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> or
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> call, but you can apply it
      to the function result. For example, these are legal:
    </p><pre data-lang="sql" class="programlisting">SELECT CONVERT('test' USING utf8mb4) COLLATE utf8mb4_bin;
SELECT CONVERT('test', CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin;
SELECT CAST('test' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin;</pre><p>
      But these are illegal:
    </p><pre data-lang="sql" class="programlisting">SELECT CONVERT('test' USING utf8mb4 COLLATE utf8mb4_bin);
SELECT CONVERT('test', CHAR CHARACTER SET utf8mb4 COLLATE utf8mb4_bin);
SELECT CAST('test' AS CHAR CHARACTER SET utf8mb4 COLLATE utf8mb4_bin);</pre><p>
      Normally, you cannot compare a <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a>
      value or other binary string in case-insensitive fashion because
      binary strings use the <code class="literal">binary</code> character set,
      which has no collation with the concept of lettercase. To perform
      a case-insensitive comparison, first use the
      <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> or
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> function to convert the
      value to a nonbinary string. Comparisons of the resulting string
      use its collation. For example, if the conversion result character
      set has a case-insensitive collation, a
      <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a> operation is not case-sensitive.
      That is true for the following operation because the default
      <code class="literal">utf8mb4</code> collation
      (<code class="literal">utf8mb4_0900_ai_ci</code>) is not case-sensitive:
    </p><pre data-lang="sql" class="programlisting">SELECT 'A' LIKE CONVERT(<em class="replaceable"><code>blob_col</code></em> USING utf8mb4)
  FROM <em class="replaceable"><code>tbl_name</code></em>;
</pre><p>
      To specify a particular collation for the converted string, use a
      <code class="literal">COLLATE</code> clause following the
      <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> call:
    </p><pre data-lang="sql" class="programlisting">SELECT 'A' LIKE CONVERT(<em class="replaceable"><code>blob_col</code></em> USING utf8mb4) COLLATE utf8mb4_unicode_ci
  FROM <em class="replaceable"><code>tbl_name</code></em>;
</pre><p>
      To use a different character set, substitute its name for
      <code class="literal">utf8mb4</code> in the preceding statements (and
      similarly to use a different collation).
    </p><p>
      <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> and
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> can be used more generally
      for comparing strings represented in different character sets. For
      example, a comparison of these strings results in an error because
      they have different character sets:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s1 = _latin1 'abc', @s2 = _latin2 'abc';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @s1 = @s2;</code></strong>
ERROR 1267 (HY000): Illegal mix of collations (latin1_swedish_ci,IMPLICIT)
and (latin2_general_ci,IMPLICIT) for operation '='
</pre><p>
      Converting one of the strings to a character set compatible with
      the other enables the comparison to occur without error:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT @s1 = CONVERT(@s2 USING latin1);</code></strong>
+---------------------------------+
| @s1 = CONVERT(@s2 USING latin1) |
+---------------------------------+
|                               1 |
+---------------------------------+
</pre><p>
      For string literals, another way to specify the character set is
      to use a character set introducer. <code class="literal">_latin1</code> and
      <code class="literal">_latin2</code> in the preceding example are instances
      of introducers. Unlike conversion functions such as
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a>, or
      <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a>, which convert a string
      from one character set to another, an introducer designates a
      string literal as having a particular character set, with no
      conversion involved. For more information, see
      <a class="xref" href="charset.html#charset-introducer" title="10.3.8 Character Set Introducers">Section 10.3.8, “Character Set Introducers”</a>.
    </p><p>
      Character set conversion is also useful preceding lettercase
      conversion of binary strings.
      <a class="link" href="functions.html#function_lower"><code class="literal">LOWER()</code></a> and
      <a class="link" href="functions.html#function_upper"><code class="literal">UPPER()</code></a> are ineffective when
      applied directly to binary strings because the concept of
      lettercase does not apply. To perform lettercase conversion of a
      binary string, first convert it to a nonbinary string using a
      character set appropriate for the data stored in the string:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @str = BINARY 'New York';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT LOWER(@str), LOWER(CONVERT(@str USING utf8mb4));</code></strong>
+-------------+------------------------------------+
| LOWER(@str) | LOWER(CONVERT(@str USING utf8mb4)) |
+-------------+------------------------------------+
| New York    | new york                           |
+-------------+------------------------------------+
</pre><p>
      Be aware that if you convert an indexed column using
      <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a>,
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a>, or
      <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a>, MySQL may not be able to
      use the index efficiently.
    </p><p>
      The cast functions are useful for creating a column with a
      specific type in a
      <a class="link" href="sql-statements.html#create-table" title="13.1.20 CREATE TABLE Statement"><code class="literal">CREATE TABLE ...
      SELECT</code></a> statement:
    </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE) AS c1;</code></strong>
mysql&gt; <strong class="userinput"><code>SHOW CREATE TABLE new_table\G</code></strong>
*************************** 1. row ***************************
       Table: new_table
Create Table: CREATE TABLE `new_table` (
  `c1` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
</pre><p>
      The cast functions are useful for sorting
      <a class="link" href="data-types.html#enum" title="11.3.5 The ENUM Type"><code class="literal">ENUM</code></a> columns in lexical order.
      Normally, sorting of <a class="link" href="data-types.html#enum" title="11.3.5 The ENUM Type"><code class="literal">ENUM</code></a> columns
      occurs using the internal numeric values. Casting the values to
      <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a> results in a lexical sort:
    </p><pre data-lang="sql" class="programlisting">SELECT <em class="replaceable"><code>enum_col</code></em> FROM <em class="replaceable"><code>tbl_name</code></em> ORDER BY CAST(<em class="replaceable"><code>enum_col</code></em> AS CHAR);
</pre><p>
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> also changes the result if
      you use it as part of a more complex expression such as
      <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT('Date: ',CAST(NOW() AS
      DATE))</code></a>.
    </p><p>
      For temporal values, there is little need to use
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> to extract data in different
      formats. Instead, use a function such as
      <a class="link" href="functions.html#function_extract"><code class="literal">EXTRACT()</code></a>,
      <a class="link" href="functions.html#function_date-format"><code class="literal">DATE_FORMAT()</code></a>, or
      <a class="link" href="functions.html#function_time-format"><code class="literal">TIME_FORMAT()</code></a>. See
      <a class="xref" href="functions.html#date-and-time-functions" title="12.6 Date and Time Functions">Section 12.6, “Date and Time Functions”</a>.
    </p><p>
      To cast a string to a number, you normally need do nothing other
      than use the string value in numeric context:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1+'1';</code></strong>
       -&gt; 2
</pre><p>
      That is also true for hexadecimal and bit literals, which are
      binary strings by default:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT X'41', X'41'+0;</code></strong>
        -&gt; 'A', 65
mysql&gt; <strong class="userinput"><code>SELECT b'1100001', b'1100001'+0;</code></strong>
        -&gt; 'a', 97
</pre><p>
      A string used in an arithmetic operation is converted to a
      floating-point number during expression evaluation.
    </p><p>
      A number used in string context is converted to a string:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CONCAT('hello you ',2);</code></strong>
        -&gt; 'hello you 2'
</pre><p>
      For information about implicit conversion of numbers to strings,
      see <a class="xref" href="functions.html#type-conversion" title="12.2 Type Conversion in Expression Evaluation">Section 12.2, “Type Conversion in Expression Evaluation”</a>.
    </p><p>
      MySQL supports arithmetic with both signed and unsigned 64-bit
      values. For numeric operators (such as
      <a class="link" href="functions.html#operator_plus"><code class="literal">+</code></a> or
      <a class="link" href="functions.html#operator_minus"><code class="literal">-</code></a>) where one of the
      operands is an unsigned integer, the result is unsigned by default
      (see <a class="xref" href="functions.html#arithmetic-functions" title="12.5.1 Arithmetic Operators">Section 12.5.1, “Arithmetic Operators”</a>). To override this,
      use the <code class="literal">SIGNED</code> or <code class="literal">UNSIGNED</code>
      cast operator to cast a value to a signed or unsigned 64-bit
      integer, respectively.
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 - 2;</code></strong>
        -&gt; -1
mysql&gt; <strong class="userinput"><code>SELECT CAST(1 - 2 AS UNSIGNED);</code></strong>
        -&gt; 18446744073709551615
mysql&gt; <strong class="userinput"><code>SELECT CAST(CAST(1 - 2 AS UNSIGNED) AS SIGNED);</code></strong>
        -&gt; -1
</pre><p>
      If either operand is a floating-point value, the result is a
      floating-point value and is not affected by the preceding rule.
      (In this context, <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> column
      values are regarded as floating-point values.)
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CAST(1 AS UNSIGNED) - 2.0;</code></strong>
        -&gt; -1.0
</pre><p>
      The SQL mode affects the result of conversion operations (see
      <a class="xref" href="server-administration.html#sql-mode" title="5.1.11 Server SQL Modes">Section 5.1.11, “Server SQL Modes”</a>). Examples:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          For conversion of a <span class="quote">“<span class="quote">zero</span>”</span> date string to a date,
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> and
          <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> return
          <code class="literal">NULL</code> and produce a warning when the
          <a class="link" href="server-administration.html#sqlmode_no_zero_date"><code class="literal">NO_ZERO_DATE</code></a> SQL mode is
          enabled.
        </p></li><li class="listitem"><p>
          For integer subtraction, if the
          <a class="link" href="server-administration.html#sqlmode_no_unsigned_subtraction"><code class="literal">NO_UNSIGNED_SUBTRACTION</code></a> SQL
          mode is enabled, the subtraction result is signed even if any
          operand is unsigned.
</p></li></ul>
</div>
<p>
      The following list describes the available cast functions and
      operators:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_binary"></a><p>
          <a class="indexterm" name="idm46444326350688"></a>

          <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a>
          <em class="replaceable"><code>expr</code></em>
        </p><p>
          The <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a> operator converts the
          expression to a binary string (a string that has the
          <code class="literal">binary</code> character set and
          <code class="literal">binary</code> collation). A common use for
          <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a> is to force a character
          string comparison to be done byte by byte using numeric byte
          values rather than character by character. The
          <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a> operator also causes
          trailing spaces in comparisons to be significant. For
          information about the differences between the
          <code class="literal">binary</code> collation of the
          <code class="literal">binary</code> character set and the
          <code class="literal">_bin</code> collations of nonbinary character
          sets, see <a class="xref" href="charset.html#charset-binary-collations" title="10.8.5 The binary Collation Compared to _bin Collations">Section 10.8.5, “The binary Collation Compared to _bin Collations”</a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'a' = 'A';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT BINARY 'a' = 'A';</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 'a' = 'a ';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT BINARY 'a' = 'a ';</code></strong>
        -&gt; 0
</pre><p>
          In a comparison, <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a> affects
          the entire operation; it can be given before either operand
          with the same result.
        </p><p>
          To convert a string expression to a binary string, these
          constructs are equivalent:
        </p><pre data-lang="sql" class="programlisting">BINARY <em class="replaceable"><code>expr</code></em>
CAST(<em class="replaceable"><code>expr</code></em> AS BINARY)
CONVERT(<em class="replaceable"><code>expr</code></em> USING BINARY)
</pre><p>
          If a value is a string literal, it can be designated as a
          binary string without performing any conversion by using the
          <code class="literal">_binary</code> character set introducer:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'a' = 'A';</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT _binary 'a' = 'A';</code></strong>
        -&gt; 0
</pre><p>
          For information about introducers, see
          <a class="xref" href="charset.html#charset-introducer" title="10.3.8 Character Set Introducers">Section 10.3.8, “Character Set Introducers”</a>.
        </p><p>
          The <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a> operator in
          expressions differs in effect from the
          <code class="literal">BINARY</code> attribute in character column
          definitions. A character column defined with the
          <code class="literal">BINARY</code> attribute is assigned the table
          default character set and the binary (<code class="literal">_bin</code>)
          collation of that character set. Every nonbinary character set
          has a <code class="literal">_bin</code> collation. For example, if the
          table default character set is <code class="literal">utf8mb4</code>,
          these two column definitions are equivalent:
        </p><pre data-lang="sql" class="programlisting">CHAR(10) BINARY
CHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin</pre><p>
          The use of <code class="literal">CHARACTER SET binary</code> in the
          definition of a <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a>,
          <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>, or
          <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">TEXT</code></a> column causes the column
          to be treated as the corresponding binary string data type.
          For example, the following pairs of definitions are
          equivalent:
        </p><pre data-lang="sql" class="programlisting">CHAR(10) CHARACTER SET binary
BINARY(10)

VARCHAR(10) CHARACTER SET binary
VARBINARY(10)

TEXT CHARACTER SET binary
BLOB</pre></li><li class="listitem"><a name="function_cast"></a><p>
          <a class="indexterm" name="idm46444326308000"></a>

          <a class="link" href="functions.html#function_cast"><code class="literal">CAST(<em class="replaceable"><code>expr</code></em> AS
          <em class="replaceable"><code>type</code></em> [ARRAY])</code></a>
        </p><p>
          The <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> function takes an
          expression of any type and produces a result value of the
          specified type, similar to
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a>. For more
          information, see the description of
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a>.
        </p><p>
          In MySQL 8.0.17 and later, <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a>
          allows the use of an additional <code class="literal">ARRAY</code>
          keyword for creating a multi-valued index on a
          <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> array as part of
          <a class="link" href="sql-statements.html#create-index" title="13.1.15 CREATE INDEX Statement"><code class="literal">CREATE INDEX</code></a>,
          <a class="link" href="sql-statements.html#create-table" title="13.1.20 CREATE TABLE Statement"><code class="literal">CREATE TABLE</code></a>, and
          <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER TABLE</code></a> statements.
          <code class="literal">ARRAY</code> is not supported except when used to
          create a multi-valued index in one of these statements, in
          which case it is required. The column being indexed must be a
          column of type <code class="literal">JSON</code>.
          (<a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> does
          <span class="emphasis"><em>not</em></span> support multi-valued index creation
          or the <code class="literal">ARRAY</code> keyword.) With
          <code class="literal">ARRAY</code>, the <em class="replaceable"><code>type</code></em>
          following the <code class="literal">AS</code> keyword may specify any of
          the types supported by <code class="literal">CAST()</code>, with the
          exceptions of <code class="literal">BINARY</code> and
          <code class="literal">JSON</code>. For syntax information and examples,
          as well as other relevant information, see
          <a class="xref" href="sql-statements.html#create-index-multi-valued" title="Multi-Valued Indexes">Multi-Valued Indexes</a>.
        </p><p>
          <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> is standard SQL syntax.
        </p></li><li class="listitem"><a name="function_convert"></a><p>
          <a class="indexterm" name="idm46444326277696"></a>

          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT(<em class="replaceable"><code>expr</code></em>,<em class="replaceable"><code>type</code></em>)</code></a>,
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT(<em class="replaceable"><code>expr</code></em>
          USING <em class="replaceable"><code>transcoding_name</code></em>)</code></a>
        </p><p>
          The <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> function takes an
          expression of any type and produces a result value of the
          specified type.
        </p><p>
          Discussion of
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT(<em class="replaceable"><code>expr</code></em>,
          <em class="replaceable"><code>type</code></em>)</code></a> syntax here also
          applies to
          <a class="link" href="functions.html#function_cast"><code class="literal">CAST(<em class="replaceable"><code>expr</code></em> AS
          <em class="replaceable"><code>type</code></em>)</code></a>, which is
          equivalent.
        </p><p>
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT(... USING ...)</code></a> is
          standard SQL syntax. The non-<code class="literal">USING</code> form of
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> is ODBC syntax.
        </p><p>
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> with
          <code class="literal">USING</code> converts data between different
          character sets. In MySQL, transcoding names are the same as
          the corresponding character set names. For example, this
          statement converts the string <code class="literal">'abc'</code> in the
          default character set to the corresponding string in the
          <code class="literal">utf8mb4</code> character set:
        </p><pre data-lang="sql" class="programlisting">SELECT CONVERT('abc' USING utf8mb4);</pre><p>
          <a class="link" href="functions.html#function_convert"><code class="literal">CONVERT()</code></a> without
          <code class="literal">USING</code> and
          <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a> take an expression and a
          <em class="replaceable"><code>type</code></em> value specifying the result
          type. These <em class="replaceable"><code>type</code></em> values are
          permitted:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">BINARY[(<em class="replaceable"><code>N</code></em>)]</code>
            </p><p>
              Produces a string with the
              <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a> data type. For a
              description of how this affects comparisons, see
              <a class="xref" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types">Section 11.3.3, “The BINARY and VARBINARY Types”</a>. If the optional length
              <em class="replaceable"><code>N</code></em> is given,
              <code class="literal">BINARY(<em class="replaceable"><code>N</code></em>)</code>
              causes the cast to use no more than
              <em class="replaceable"><code>N</code></em> bytes of the argument. Values
              shorter than <em class="replaceable"><code>N</code></em> bytes are padded
              with <code class="literal">0x00</code> bytes to a length of
              <em class="replaceable"><code>N</code></em>.
            </p></li><li class="listitem"><p>
              <code class="literal">CHAR[(<em class="replaceable"><code>N</code></em>)]
              [<em class="replaceable"><code>charset_info</code></em>]</code>
            </p><p>
              Produces a string with the
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a> data type. If the
              optional length <em class="replaceable"><code>N</code></em> is given,
              <code class="literal">CHAR(<em class="replaceable"><code>N</code></em>)</code>
              causes the cast to use no more than
              <em class="replaceable"><code>N</code></em> characters of the argument.
              No padding occurs for values shorter than
              <em class="replaceable"><code>N</code></em> characters.
            </p><p>
              With no <em class="replaceable"><code>charset_info</code></em> clause,
              <code class="literal">CHAR</code> produces a string with the default
              character set. To specify the character set explicitly,
              these <em class="replaceable"><code>charset_info</code></em> values are
              permitted:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  <code class="literal">CHARACTER SET
                  <em class="replaceable"><code>charset_name</code></em></code>:
                  Produces a string with the given character set.
                </p></li><li class="listitem"><p>
                  <code class="literal">ASCII</code>: Shorthand for
                  <code class="literal">CHARACTER SET latin1</code>.
                </p></li><li class="listitem"><p>
                  <code class="literal">UNICODE</code>: Shorthand for
                  <code class="literal">CHARACTER SET ucs2</code>.
</p></li></ul>
</div>
<p>
              In all cases, the string has the character set default
              collation.
            </p></li><li class="listitem"><p>
              <code class="literal">DATE</code>
            </p><p>
              Produces a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> value.
            </p></li><li class="listitem"><p>
              <code class="literal">DATETIME</code>
            </p><p>
              Produces a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> value.
            </p></li><li class="listitem"><p>
              <code class="literal">DECIMAL[(<em class="replaceable"><code>M</code></em>[,<em class="replaceable"><code>D</code></em>])]</code>
            </p><p>
              Produces a <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> value.
              If the optional <em class="replaceable"><code>M</code></em> and
              <em class="replaceable"><code>D</code></em> values are given, they
              specify the maximum number of digits (the precision) and
              the number of digits following the decimal point (the
              scale).
            </p></li><li class="listitem"><p>
              <code class="literal">DOUBLE</code>
            </p><p>
              Produces a <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a> result.
              Added in MySQL 8.0.17.
            </p></li><li class="listitem"><p>
              <code class="literal">FLOAT[(<em class="replaceable"><code>p</code></em>)]</code>
            </p><p>
              If the precision <em class="replaceable"><code>p</code></em> is not
              specified, produces a result of type
              <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a>. If
              <em class="replaceable"><code>p</code></em> is provided and 0 &lt;= &lt;
              <em class="replaceable"><code>p</code></em> &lt;= 24, the result is of
              type <code class="literal">FLOAT</code>. If 25 &lt;=
              <em class="replaceable"><code>p</code></em> &lt;= 53, the result is of
              type <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a>. If
              <em class="replaceable"><code>p</code></em> &lt; 0 or
              <em class="replaceable"><code>p</code></em> &gt; 53, an error is
              returned. Added in MySQL 8.0.17.
            </p></li><li class="listitem"><p>
              <code class="literal">JSON</code>
            </p><p>
              Produces a <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> value. For
              details on the rules for conversion of values between
              <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> and other types, see
              <a class="xref" href="data-types.html#json-comparison" title="Comparison and Ordering of JSON Values">Comparison and Ordering of JSON Values</a>.
            </p></li><li class="listitem"><p>
              <code class="literal">NCHAR[(<em class="replaceable"><code>N</code></em>)]</code>
            </p><p>
              Like <code class="literal">CHAR</code>, but produces a string with
              the national character set. See
              <a class="xref" href="charset.html#charset-national" title="10.3.7 The National Character Set">Section 10.3.7, “The National Character Set”</a>.
            </p><p>
              Unlike <code class="literal">CHAR</code>, <code class="literal">NCHAR</code>
              does not permit trailing character set information to be
              specified.
            </p></li><li class="listitem"><p>
              <code class="literal">REAL</code>
            </p><p>
              Produces a result of type
              <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">REAL</code></a>. This is actually
              <code class="literal">FLOAT</code> if
              <code class="literal">REAL_AS_FLOAT</code> SQL mode
              is enabled; otherwise the result is of type
              <code class="literal">DOUBLE</code>.
            </p></li><li class="listitem"><p>
              <code class="literal">SIGNED [INTEGER]</code>
            </p><p>
              Produces a signed integer value.
            </p></li><li class="listitem"><p>
              <code class="literal">TIME</code>
            </p><p>
              Produces a <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a> value.
            </p></li><li class="listitem"><p>
              <code class="literal">UNSIGNED [INTEGER]</code>
            </p><p>
              Produces an unsigned integer value.
</p></li></ul>
</div>
</li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="xml-functions"></a>12.11 XML Functions</h2>

</div>

</div>

</div>

<div class="table">
<a name="idm46444326179296"></a><p class="title"><b>Table 12.15 XML Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists XML functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a></td>
<td>
      Extract a value from an XML string using XPath notation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_updatexml"><code class="literal">UpdateXML()</code></a></td>
<td>
      Return replaced XML fragment
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      This section discusses XML and related functionality in MySQL.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
        It is possible to obtain XML-formatted output from MySQL in the
        <a class="link" href="programs.html#mysql" title="4.5.1 mysql — The MySQL Command-Line Client"><span class="command"><strong>mysql</strong></span></a> and <a class="link" href="programs.html#mysqldump" title="4.5.4 mysqldump — A Database Backup Program"><span class="command"><strong>mysqldump</strong></span></a>
        clients by invoking them with the
        <a class="link" href="programs.html#option_mysql_xml"><code class="option">--xml</code></a> option. See
        <a class="xref" href="programs.html#mysql" title="4.5.1 mysql — The MySQL Command-Line Client">Section 4.5.1, “<span class="command"><strong>mysql</strong></span> — The MySQL Command-Line Client”</a>, and <a class="xref" href="programs.html#mysqldump" title="4.5.4 mysqldump — A Database Backup Program">Section 4.5.4, “<span class="command"><strong>mysqldump</strong></span> — A Database Backup Program”</a>.
</p>
</div>
<p>
      Two functions providing basic XPath 1.0 (XML Path Language,
      version 1.0) capabilities are available. Some basic information
      about XPath syntax and usage is provided later in this section;
      however, an in-depth discussion of these topics is beyond the
      scope of this manual, and you should refer to the
      <a class="ulink" href="http://www.w3.org/TR/xpath" target="_top">XML Path Language (XPath)
      1.0 standard</a> for definitive information. A useful resource
      for those new to XPath or who desire a refresher in the basics is
      the <a class="ulink" href="http://www.zvon.org/xxl/XPathTutorial/" target="_top">Zvon.org
      XPath Tutorial</a>, which is available in several languages.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
        These functions remain under development. We continue to improve
        these and other aspects of XML and XPath functionality in MySQL
        8.0 and onwards. You may discuss these, ask
        questions about them, and obtain help from other users with them
        in the <a class="ulink" href="https://forums.mysql.com/list.php?44" target="_top">MySQL XML User
        Forum</a>.
</p>
</div>
<p>
      XPath expressions used with these functions support user variables
      and local stored program variables. User variables are weakly
      checked; variables local to stored programs are strongly checked
      (see also Bug #26518):
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><b>User variables (weak checking). </b>
            Variables using the syntax
            <code class="literal">$@<em class="replaceable"><code>variable_name</code></em></code>
            (that is, user variables) are not checked. No warnings or
            errors are issued by the server if a variable has the wrong
            type or has previously not been assigned a value. This also
            means the user is fully responsible for any typographical
            errors, since no warnings will be given if (for example)
            <code class="literal">$@myvariable</code> is used where
            <code class="literal">$@myvariable</code> was intended.
          </p><p>
          Example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @xml = '&lt;a&gt;&lt;b&gt;X&lt;/b&gt;&lt;b&gt;Y&lt;/b&gt;&lt;/a&gt;';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @i =1, @j = 2;</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @i, ExtractValue(@xml, '//b[$@i]');</code></strong>
+------+--------------------------------+
| @i   | ExtractValue(@xml, '//b[$@i]') |
+------+--------------------------------+
|    1 | X                              |
+------+--------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @j, ExtractValue(@xml, '//b[$@j]');</code></strong>
+------+--------------------------------+
| @j   | ExtractValue(@xml, '//b[$@j]') |
+------+--------------------------------+
|    2 | Y                              |
+------+--------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @k, ExtractValue(@xml, '//b[$@k]');</code></strong>
+------+--------------------------------+
| @k   | ExtractValue(@xml, '//b[$@k]') |
+------+--------------------------------+
| NULL |                                |
+------+--------------------------------+
1 row in set (0.00 sec)
</pre></li><li class="listitem"><p><b>Variables in stored programs (strong checking). </b>
            Variables using the syntax
            <code class="literal">$<em class="replaceable"><code>variable_name</code></em></code>
            can be declared and used with these functions when they are
            called inside stored programs. Such variables are local to
            the stored program in which they are defined, and are
            strongly checked for type and value.
          </p><p>
          Example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>DELIMITER |</code></strong>

mysql&gt; <strong class="userinput"><code>CREATE PROCEDURE myproc ()</code></strong>
    -&gt; <strong class="userinput"><code>BEGIN</code></strong>
    -&gt;   <strong class="userinput"><code>DECLARE i INT DEFAULT 1;</code></strong>
    -&gt;   <strong class="userinput"><code>DECLARE xml VARCHAR(25) DEFAULT '&lt;a&gt;X&lt;/a&gt;&lt;a&gt;Y&lt;/a&gt;&lt;a&gt;Z&lt;/a&gt;';</code></strong>
    -&gt;
    -&gt;   <strong class="userinput"><code>WHILE i &lt; 4 DO</code></strong>
    -&gt;     <strong class="userinput"><code>SELECT xml, i, ExtractValue(xml, '//a[$i]');</code></strong>
    -&gt;     <strong class="userinput"><code>SET i = i+1;</code></strong>
    -&gt;   <strong class="userinput"><code>END WHILE;</code></strong>
    -&gt; <strong class="userinput"><code>END |</code></strong>
Query OK, 0 rows affected (0.01 sec)

mysql&gt; <strong class="userinput"><code>DELIMITER ;</code></strong>

mysql&gt; <strong class="userinput"><code>CALL myproc();</code></strong>
+--------------------------+---+------------------------------+
| xml                      | i | ExtractValue(xml, '//a[$i]') |
+--------------------------+---+------------------------------+
| &lt;a&gt;X&lt;/a&gt;&lt;a&gt;Y&lt;/a&gt;&lt;a&gt;Z&lt;/a&gt; | 1 | X                            |
+--------------------------+---+------------------------------+
1 row in set (0.00 sec)

+--------------------------+---+------------------------------+
| xml                      | i | ExtractValue(xml, '//a[$i]') |
+--------------------------+---+------------------------------+
| &lt;a&gt;X&lt;/a&gt;&lt;a&gt;Y&lt;/a&gt;&lt;a&gt;Z&lt;/a&gt; | 2 | Y                            |
+--------------------------+---+------------------------------+
1 row in set (0.01 sec)

+--------------------------+---+------------------------------+
| xml                      | i | ExtractValue(xml, '//a[$i]') |
+--------------------------+---+------------------------------+
| &lt;a&gt;X&lt;/a&gt;&lt;a&gt;Y&lt;/a&gt;&lt;a&gt;Z&lt;/a&gt; | 3 | Z                            |
+--------------------------+---+------------------------------+
1 row in set (0.01 sec)
</pre><p><b>Parameters. </b>
            Variables used in XPath expressions inside stored routines
            that are passed in as parameters are also subject to strong
            checking.
</p></li></ul>
</div>
<p>
      Expressions containing user variables or variables local to stored
      programs must otherwise (except for notation) conform to the rules
      for XPath expressions containing variables as given in the XPath
      1.0 specification.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
        A user variable used to store an XPath expression is treated as
        an empty string. Because of this, it is not possible to store an
        XPath expression as a user variable. (Bug #32911)
</p>
</div>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_extractvalue"></a><p>
          <a class="indexterm" name="idm46444326124128"></a>

          <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue(<em class="replaceable"><code>xml_frag</code></em>,
          <em class="replaceable"><code>xpath_expr</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a> takes two string
          arguments, a fragment of XML markup
          <em class="replaceable"><code>xml_frag</code></em> and an XPath expression
          <em class="replaceable"><code>xpath_expr</code></em> (also known as a
          <span class="firstterm">locator</span>); it returns the
          text (<code class="literal">CDATA</code>) of the first text node which
          is a child of the element or elements matched by the XPath
          expression.
        </p><p>
          Using this function is the equivalent of performing a match
          using the <em class="replaceable"><code>xpath_expr</code></em> after
          appending <code class="literal">/text()</code>. In other words,
          <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue('&lt;a&gt;&lt;b&gt;Sakila&lt;/b&gt;&lt;/a&gt;',
          '/a/b')</code></a> and
          <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue('&lt;a&gt;&lt;b&gt;Sakila&lt;/b&gt;&lt;/a&gt;',
          '/a/b/text()')</code></a> produce the same result.
        </p><p>
          If multiple matches are found, the content of the first child
          text node of each matching element is returned (in the order
          matched) as a single, space-delimited string.
        </p><p>
          If no matching text node is found for the expression
          (including the implicit <code class="literal">/text()</code>)—for
          whatever reason, as long as
          <em class="replaceable"><code>xpath_expr</code></em> is valid, and
          <em class="replaceable"><code>xml_frag</code></em> consists of elements which
          are properly nested and closed—an empty string is
          returned. No distinction is made between a match on an empty
          element and no match at all. This is by design.
        </p><p>
          If you need to determine whether no matching element was found
          in <em class="replaceable"><code>xml_frag</code></em> or such an element was
          found but contained no child text nodes, you should test the
          result of an expression that uses the XPath
          <code class="literal">count()</code> function. For example, both of
          these statements return an empty string, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;&lt;b/&gt;&lt;/a&gt;', '/a/b');</code></strong>
+-------------------------------------+
| ExtractValue('&lt;a&gt;&lt;b/&gt;&lt;/a&gt;', '/a/b') |
+-------------------------------------+
|                                     |
+-------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;&lt;c/&gt;&lt;/a&gt;', '/a/b');</code></strong>
+-------------------------------------+
| ExtractValue('&lt;a&gt;&lt;c/&gt;&lt;/a&gt;', '/a/b') |
+-------------------------------------+
|                                     |
+-------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          However, you can determine whether there was actually a
          matching element using the following:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;&lt;b/&gt;&lt;/a&gt;', 'count(/a/b)');</code></strong>
+-------------------------------------+
| ExtractValue('&lt;a&gt;&lt;b/&gt;&lt;/a&gt;', 'count(/a/b)') |
+-------------------------------------+
| 1                                   |
+-------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;&lt;c/&gt;&lt;/a&gt;', 'count(/a/b)');</code></strong>
+-------------------------------------+
| ExtractValue('&lt;a&gt;&lt;c/&gt;&lt;/a&gt;', 'count(/a/b)') |
+-------------------------------------+
| 0                                   |
+-------------------------------------+
1 row in set (0.01 sec)
</pre>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Important
</div>
<p>
            <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a> returns only
            <code class="literal">CDATA</code>, and does not return any tags that
            might be contained within a matching tag, nor any of their
            content (see the result returned as <code class="literal">val1</code>
            in the following example).
</p>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt; <strong class="userinput"><code>  ExtractValue('&lt;a&gt;ccc&lt;b&gt;ddd&lt;/b&gt;&lt;/a&gt;', '/a') AS val1,</code></strong>
    -&gt; <strong class="userinput"><code>  ExtractValue('&lt;a&gt;ccc&lt;b&gt;ddd&lt;/b&gt;&lt;/a&gt;', '/a/b') AS val2,</code></strong>
    -&gt; <strong class="userinput"><code>  ExtractValue('&lt;a&gt;ccc&lt;b&gt;ddd&lt;/b&gt;&lt;/a&gt;', '//b') AS val3,</code></strong>
    -&gt; <strong class="userinput"><code>  ExtractValue('&lt;a&gt;ccc&lt;b&gt;ddd&lt;/b&gt;&lt;/a&gt;', '/b') AS val4,</code></strong>
    -&gt; <strong class="userinput"><code>  ExtractValue('&lt;a&gt;ccc&lt;b&gt;ddd&lt;/b&gt;&lt;b&gt;eee&lt;/b&gt;&lt;/a&gt;', '//b') AS val5;</code></strong>

+------+------+------+------+---------+
| val1 | val2 | val3 | val4 | val5    |
+------+------+------+------+---------+
| ccc  | ddd  | ddd  |      | ddd eee |
+------+------+------+------+---------+
</pre><p>
          This function uses the current SQL collation for making
          comparisons with <code class="literal">contains()</code>, performing the
          same collation aggregation as other string functions (such as
          <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a>), in taking into
          account the collation coercibility of their arguments; see
          <a class="xref" href="charset.html#charset-collation-coercibility" title="10.8.4 Collation Coercibility in Expressions">Section 10.8.4, “Collation Coercibility in Expressions”</a>, for an
          explanation of the rules governing this behavior.
        </p><p>
          (Previously, binary—that is,
          case-sensitive—comparison was always used.)
        </p><p>
          <code class="literal">NULL</code> is returned if
          <em class="replaceable"><code>xml_frag</code></em> contains elements which
          are not properly nested or closed, and a warning is generated,
          as shown in this example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b', '//a');</code></strong>
+-----------------------------------+
| ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b', '//a') |
+-----------------------------------+
| NULL                              |
+-----------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS\G</code></strong>
*************************** 1. row ***************************
  Level: Warning
   Code: 1525
Message: Incorrect XML value: 'parse error at line 1 pos 11:
         END-OF-INPUT unexpected ('&gt;' wanted)'
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b/&gt;', '//a');</code></strong>
+-------------------------------------+
| ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b/&gt;', '//a') |
+-------------------------------------+
| c                                   |
+-------------------------------------+
1 row in set (0.00 sec)
</pre></li><li class="listitem"><a name="function_updatexml"></a><p>
          <a class="indexterm" name="idm46444326075360"></a>

          <a class="link" href="functions.html#function_updatexml"><code class="literal">UpdateXML(<em class="replaceable"><code>xml_target</code></em>,
          <em class="replaceable"><code>xpath_expr</code></em>,
          <em class="replaceable"><code>new_xml</code></em>)</code></a>
        </p><p>
          This function replaces a single portion of a given fragment of
          XML markup <em class="replaceable"><code>xml_target</code></em> with a new
          XML fragment <em class="replaceable"><code>new_xml</code></em>, and then
          returns the changed XML. The portion of
          <em class="replaceable"><code>xml_target</code></em> that is replaced matches
          an XPath expression <em class="replaceable"><code>xpath_expr</code></em>
          supplied by the user.
        </p><p>
          If no expression matching
          <em class="replaceable"><code>xpath_expr</code></em> is found, or if multiple
          matches are found, the function returns the original
          <em class="replaceable"><code>xml_target</code></em> XML fragment. All three
          arguments should be strings.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt; <strong class="userinput"><code>  UpdateXML('&lt;a&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;', '/a', '&lt;e&gt;fff&lt;/e&gt;') AS val1,</code></strong>
    -&gt; <strong class="userinput"><code>  UpdateXML('&lt;a&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;', '/b', '&lt;e&gt;fff&lt;/e&gt;') AS val2,</code></strong>
    -&gt; <strong class="userinput"><code>  UpdateXML('&lt;a&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;', '//b', '&lt;e&gt;fff&lt;/e&gt;') AS val3,</code></strong>
    -&gt; <strong class="userinput"><code>  UpdateXML('&lt;a&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;', '/a/d', '&lt;e&gt;fff&lt;/e&gt;') AS val4,</code></strong>
    -&gt; <strong class="userinput"><code>  UpdateXML('&lt;a&gt;&lt;d&gt;&lt;/d&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;', '/a/d', '&lt;e&gt;fff&lt;/e&gt;') AS val5</code></strong>
    -&gt; <strong class="userinput"><code>\G</code></strong>

*************************** 1. row ***************************
val1: &lt;e&gt;fff&lt;/e&gt;
val2: &lt;a&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;
val3: &lt;a&gt;&lt;e&gt;fff&lt;/e&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;
val4: &lt;a&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;e&gt;fff&lt;/e&gt;&lt;/a&gt;
val5: &lt;a&gt;&lt;d&gt;&lt;/d&gt;&lt;b&gt;ccc&lt;/b&gt;&lt;d&gt;&lt;/d&gt;&lt;/a&gt;
</pre></li></ul>
</div>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<div class="admon-title">
Note
</div>
<p>
        A discussion in depth of XPath syntax and usage are beyond the
        scope of this manual. Please see the
        <a class="ulink" href="http://www.w3.org/TR/xpath" target="_top">XML Path Language
        (XPath) 1.0 specification</a> for definitive information. A
        useful resource for those new to XPath or who are wishing a
        refresher in the basics is the
        <a class="ulink" href="http://www.zvon.org/xxl/XPathTutorial/" target="_top">Zvon.org
        XPath Tutorial</a>, which is available in several languages.
</p>
</div>
<p>
      Descriptions and examples of some basic XPath expressions follow:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          <code class="literal">/<em class="replaceable"><code>tag</code></em></code>
        </p><p>
          Matches
          <code class="literal">&lt;<em class="replaceable"><code>tag</code></em>/&gt;</code> if
          and only if
          <code class="literal">&lt;<em class="replaceable"><code>tag</code></em>/&gt;</code> is
          the root element.
        </p><p>
          Example: <code class="literal">/a</code> has a match in
          <code class="literal">&lt;a&gt;&lt;b/&gt;&lt;/a&gt;</code> because it
          matches the outermost (root) tag. It does not match the inner
          <em class="replaceable"><code>a</code></em> element in
          <code class="literal">&lt;b&gt;&lt;a/&gt;&lt;/b&gt;</code> because in
          this instance it is the child of another element.
        </p></li><li class="listitem"><p>
          <code class="literal">/<em class="replaceable"><code>tag1</code></em>/<em class="replaceable"><code>tag2</code></em></code>
        </p><p>
          Matches
          <code class="literal">&lt;<em class="replaceable"><code>tag2</code></em>/&gt;</code> if
          and only if it is a child of
          <code class="literal">&lt;<em class="replaceable"><code>tag1</code></em>/&gt;</code>,
          and
          <code class="literal">&lt;<em class="replaceable"><code>tag1</code></em>/&gt;</code> is
          the root element.
        </p><p>
          Example: <code class="literal">/a/b</code> matches the
          <em class="replaceable"><code>b</code></em> element in the XML fragment
          <code class="literal">&lt;a&gt;&lt;b/&gt;&lt;/a&gt;</code> because it is
          a child of the root element <em class="replaceable"><code>a</code></em>. It
          does not have a match in
          <code class="literal">&lt;b&gt;&lt;a/&gt;&lt;/b&gt;</code> because in
          this case, <em class="replaceable"><code>b</code></em> is the root element
          (and hence the child of no other element). Nor does the XPath
          expression have a match in
          <code class="literal">&lt;a&gt;&lt;c&gt;&lt;b/&gt;&lt;/c&gt;&lt;/a&gt;</code>;
          here, <em class="replaceable"><code>b</code></em> is a descendant of
          <em class="replaceable"><code>a</code></em>, but not actually a child of
          <em class="replaceable"><code>a</code></em>.
        </p><p>
          This construct is extendable to three or more elements. For
          example, the XPath expression <code class="literal">/a/b/c</code>
          matches the <em class="replaceable"><code>c</code></em> element in the
          fragment
          <code class="literal">&lt;a&gt;&lt;b&gt;&lt;c/&gt;&lt;/b&gt;&lt;/a&gt;</code>.
        </p></li><li class="listitem"><p>
          <code class="literal">//<em class="replaceable"><code>tag</code></em></code>
        </p><p>
          Matches any instance of
          <code class="literal">&lt;<em class="replaceable"><code>tag</code></em>&gt;</code>.
        </p><p>
          Example: <code class="literal">//a</code> matches the
          <em class="replaceable"><code>a</code></em> element in any of the following:
          <code class="literal">&lt;a&gt;&lt;b&gt;&lt;c/&gt;&lt;/b&gt;&lt;/a&gt;</code>;
          <code class="literal">&lt;c&gt;&lt;a&gt;&lt;b/&gt;&lt;/a&gt;&lt;/b&gt;</code>;
          <code class="literal">&lt;c&gt;&lt;b&gt;&lt;a/&gt;&lt;/b&gt;&lt;/c&gt;</code>.
        </p><p>
          <code class="literal">//</code> can be combined with
          <code class="literal">/</code>. For example, <code class="literal">//a/b</code>
          matches the <em class="replaceable"><code>b</code></em> element in either of
          the fragments <code class="literal">&lt;a&gt;&lt;b/&gt;&lt;/a&gt;</code>
          or
          <code class="literal">&lt;c&gt;&lt;a&gt;&lt;b/&gt;&lt;/a&gt;&lt;/c&gt;</code>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            <code class="literal">//<em class="replaceable"><code>tag</code></em></code> is the
            equivalent of
            <code class="literal">/descendant-or-self::*/<em class="replaceable"><code>tag</code></em></code>.
            A common error is to confuse this with
            <code class="literal">/descendant-or-self::<em class="replaceable"><code>tag</code></em></code>,
            although the latter expression can actually lead to very
            different results, as can be seen here:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @xml = '&lt;a&gt;&lt;b&gt;&lt;c&gt;w&lt;/c&gt;&lt;b&gt;x&lt;/b&gt;&lt;d&gt;y&lt;/d&gt;z&lt;/b&gt;&lt;/a&gt;';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @xml;</code></strong>
+-----------------------------------------+
| @xml                                    |
+-----------------------------------------+
| &lt;a&gt;&lt;b&gt;&lt;c&gt;w&lt;/c&gt;&lt;b&gt;x&lt;/b&gt;&lt;d&gt;y&lt;/d&gt;z&lt;/b&gt;&lt;/a&gt; |
+-----------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(@xml, '//b[1]');</code></strong>
+------------------------------+
| ExtractValue(@xml, '//b[1]') |
+------------------------------+
| x z                          |
+------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(@xml, '//b[2]');</code></strong>
+------------------------------+
| ExtractValue(@xml, '//b[2]') |
+------------------------------+
|                              |
+------------------------------+
1 row in set (0.01 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(@xml, '/descendant-or-self::*/b[1]');</code></strong>
+---------------------------------------------------+
| ExtractValue(@xml, '/descendant-or-self::*/b[1]') |
+---------------------------------------------------+
| x z                                               |
+---------------------------------------------------+
1 row in set (0.06 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(@xml, '/descendant-or-self::*/b[2]');</code></strong>
+---------------------------------------------------+
| ExtractValue(@xml, '/descendant-or-self::*/b[2]') |
+---------------------------------------------------+
|                                                   |
+---------------------------------------------------+
1 row in set (0.00 sec)


mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(@xml, '/descendant-or-self::b[1]');</code></strong>
+-------------------------------------------------+
| ExtractValue(@xml, '/descendant-or-self::b[1]') |
+-------------------------------------------------+
| z                                               |
+-------------------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(@xml, '/descendant-or-self::b[2]');</code></strong>
+-------------------------------------------------+
| ExtractValue(@xml, '/descendant-or-self::b[2]') |
+-------------------------------------------------+
| x                                               |
+-------------------------------------------------+
1 row in set (0.00 sec)
</pre>
</div>
</li><li class="listitem"><p>
          The <code class="literal">*</code> operator acts as a
          <span class="quote">“<span class="quote">wildcard</span>”</span> that matches any element. For example,
          the expression <code class="literal">/*/b</code> matches the
          <em class="replaceable"><code>b</code></em> element in either of the XML
          fragments <code class="literal">&lt;a&gt;&lt;b/&gt;&lt;/a&gt;</code> or
          <code class="literal">&lt;c&gt;&lt;b/&gt;&lt;/c&gt;</code>. However, the
          expression does not produce a match in the fragment
          <code class="literal">&lt;b&gt;&lt;a/&gt;&lt;/b&gt;</code> because
          <em class="replaceable"><code>b</code></em> must be a child of some other
          element. The wildcard may be used in any position: The
          expression <code class="literal">/*/b/*</code> will match any child of a
          <em class="replaceable"><code>b</code></em> element that is itself not the
          root element.
        </p></li><li class="listitem"><p>
          You can match any of several locators using the
          <code class="literal">|</code> (<a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a>)
          operator. For example, the expression
          <code class="literal">//b|//c</code> matches all
          <em class="replaceable"><code>b</code></em> and <em class="replaceable"><code>c</code></em>
          elements in the XML target.
        </p></li><li class="listitem"><p>
          It is also possible to match an element based on the value of
          one or more of its attributes. This done using the syntax
          <code class="literal"><em class="replaceable"><code>tag</code></em>[@<em class="replaceable"><code>attribute</code></em>="<em class="replaceable"><code>value</code></em>"]</code>.
          For example, the expression <code class="literal">//b[@id="idB"]</code>
          matches the second <em class="replaceable"><code>b</code></em> element in the
          fragment <code class="literal">&lt;a&gt;&lt;b id="idA"/&gt;&lt;c/&gt;&lt;b
          id="idB"/&gt;&lt;/a&gt;</code>. To match against
          <span class="emphasis"><em>any</em></span> element having
          <code class="literal"><em class="replaceable"><code>attribute</code></em>="<em class="replaceable"><code>value</code></em>"</code>,
          use the XPath expression
          <code class="literal">//*[<em class="replaceable"><code>attribute</code></em>="<em class="replaceable"><code>value</code></em>"]</code>.
        </p><p>
          To filter multiple attribute values, simply use multiple
          attribute-comparison clauses in succession. For example, the
          expression <code class="literal">//b[@c="x"][@d="y"]</code> matches the
          element <code class="literal">&lt;b c="x" d="y"/&gt;</code> occurring
          anywhere in a given XML fragment.
        </p><p>
          To find elements for which the same attribute matches any of
          several values, you can use multiple locators joined by the
          <code class="literal">|</code> operator. For example, to match all
          <em class="replaceable"><code>b</code></em> elements whose
          <em class="replaceable"><code>c</code></em> attributes have either of the
          values 23 or 17, use the expression
          <code class="literal">//b[@c="23"]|//b[@c="17"]</code>. You can also use
          the logical <code class="literal">or</code> operator for this purpose:
          <code class="literal">//b[@c="23" or @c="17"]</code>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The difference between <code class="literal">or</code> and
            <code class="literal">|</code> is that <code class="literal">or</code> joins
            conditions, while <code class="literal">|</code> joins result sets.
</p>
</div>
</li></ul>
</div>
<p><b>XPath Limitations. </b>
        The XPath syntax supported by these functions is currently
        subject to the following limitations:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Nodeset-to-nodeset comparison (such as
          <code class="literal">'/a/b[@c=@d]'</code>) is not supported.
        </p></li><li class="listitem"><p>
          All of the standard XPath comparison operators are supported.
          (Bug #22823)
        </p></li><li class="listitem"><p>
          Relative locator expressions are resolved in the context of
          the root node. For example, consider the following query and
          result:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(</code></strong>
    -&gt;   <strong class="userinput"><code>'&lt;a&gt;&lt;b c="1"&gt;X&lt;/b&gt;&lt;b c="2"&gt;Y&lt;/b&gt;&lt;/a&gt;',</code></strong>
    -&gt;    <strong class="userinput"><code>'a/b'</code></strong>
    -&gt; <strong class="userinput"><code>) AS result;</code></strong>
+--------+
| result |
+--------+
| X Y    |
+--------+
1 row in set (0.03 sec)
</pre><p>
          In this case, the locator <code class="literal">a/b</code> resolves to
          <code class="literal">/a/b</code>.
        </p><p>
          Relative locators are also supported within predicates. In the
          following example, <code class="literal">d[../@c="1"]</code> is resolved
          as <code class="literal">/a/b[@c="1"]/d</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(</code></strong>
    -&gt;      <strong class="userinput"><code>'&lt;a&gt;</code></strong>
    -&gt;        <strong class="userinput"><code>&lt;b c="1"&gt;&lt;d&gt;X&lt;/d&gt;&lt;/b&gt;</code></strong>
    -&gt;        <strong class="userinput"><code>&lt;b c="2"&gt;&lt;d&gt;X&lt;/d&gt;&lt;/b&gt;</code></strong>
    -&gt;      <strong class="userinput"><code>&lt;/a&gt;',</code></strong>
    -&gt;      <strong class="userinput"><code>'a/b/d[../@c="1"]')</code></strong>
    -&gt; <strong class="userinput"><code>AS result;</code></strong>
+--------+
| result |
+--------+
| X      |
+--------+
1 row in set (0.00 sec)
</pre></li><li class="listitem"><p>
          Locators prefixed with expressions that evaluate as scalar
          values—including variable references, literals, numbers,
          and scalar function calls—are not permitted, and their
          use results in an error.
        </p></li><li class="listitem"><p>
          The <code class="literal">::</code> operator is not supported in
          combination with node types such as the following:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>axis</code></em>::comment()</code>
            </p></li><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>axis</code></em>::text()</code>
            </p></li><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>axis</code></em>::processing-instructions()</code>
            </p></li><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>axis</code></em>::node()</code>
</p></li></ul>
</div>
<p>
          However, name tests (such as
          <code class="literal"><em class="replaceable"><code>axis</code></em>::<em class="replaceable"><code>name</code></em></code>
          and <code class="literal"><em class="replaceable"><code>axis</code></em>::*</code>) are
          supported, as shown in these examples:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;&lt;b&gt;x&lt;/b&gt;&lt;c&gt;y&lt;/c&gt;&lt;/a&gt;','/a/child::b');</code></strong>
+-------------------------------------------------------+
| ExtractValue('&lt;a&gt;&lt;b&gt;x&lt;/b&gt;&lt;c&gt;y&lt;/c&gt;&lt;/a&gt;','/a/child::b') |
+-------------------------------------------------------+
| x                                                     |
+-------------------------------------------------------+
1 row in set (0.02 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;&lt;b&gt;x&lt;/b&gt;&lt;c&gt;y&lt;/c&gt;&lt;/a&gt;','/a/child::*');</code></strong>
+-------------------------------------------------------+
| ExtractValue('&lt;a&gt;&lt;b&gt;x&lt;/b&gt;&lt;c&gt;y&lt;/c&gt;&lt;/a&gt;','/a/child::*') |
+-------------------------------------------------------+
| x y                                                   |
+-------------------------------------------------------+
1 row in set (0.01 sec)
</pre></li><li class="listitem"><p>
          <span class="quote">“<span class="quote">Up-and-down</span>”</span> navigation is not supported in
          cases where the path would lead <span class="quote">“<span class="quote">above</span>”</span> the root
          element. That is, you cannot use expressions which match on
          descendants of ancestors of a given element, where one or more
          of the ancestors of the current element is also an ancestor of
          the root element (see Bug #16321).
        </p></li><li class="listitem"><p>
          The following XPath functions are not supported, or have known
          issues as indicated:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">id()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">lang()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">local-name()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">name()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">namespace-uri()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">normalize-space()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">starts-with()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">string()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">substring-after()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">substring-before()</code>
            </p></li><li class="listitem"><p>
              <code class="literal">translate()</code>
</p></li></ul>
</div>
</li><li class="listitem"><p>
          The following axes are not supported:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">following-sibling</code>
            </p></li><li class="listitem"><p>
              <code class="literal">following</code>
            </p></li><li class="listitem"><p>
              <code class="literal">preceding-sibling</code>
            </p></li><li class="listitem"><p>
              <code class="literal">preceding</code>
</p></li></ul>
</div>
</li></ul>
</div>
<p>
      XPath expressions passed as arguments to
      <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a> and
      <a class="link" href="functions.html#function_updatexml"><code class="literal">UpdateXML()</code></a> may contain the colon
      character (<code class="literal">:</code>) in element selectors, which
      enables their use with markup employing XML namespaces notation.
      For example:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @xml = '&lt;a&gt;111&lt;b:c&gt;222&lt;d&gt;333&lt;/d&gt;&lt;e:f&gt;444&lt;/e:f&gt;&lt;/b:c&gt;&lt;/a&gt;';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(@xml, '//e:f');</code></strong>
+-----------------------------+
| ExtractValue(@xml, '//e:f') |
+-----------------------------+
| 444                         |
+-----------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT UpdateXML(@xml, '//b:c', '&lt;g:h&gt;555&lt;/g:h&gt;');</code></strong>
+--------------------------------------------+
| UpdateXML(@xml, '//b:c', '&lt;g:h&gt;555&lt;/g:h&gt;') |
+--------------------------------------------+
| &lt;a&gt;111&lt;g:h&gt;555&lt;/g:h&gt;&lt;/a&gt;                   |
+--------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
      This is similar in some respects to what is permitted by
      <a class="ulink" href="http://xalan.apache.org/" target="_top">Apache Xalan</a> and
      some other parsers, and is much simpler than requiring namespace
      declarations or the use of the <code class="literal">namespace-uri()</code>
      and <code class="literal">local-name()</code> functions.
    </p><p><b>Error handling. </b>
        For both <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a> and
        <a class="link" href="functions.html#function_updatexml"><code class="literal">UpdateXML()</code></a>, the XPath locator
        used must be valid and the XML to be searched must consist of
        elements which are properly nested and closed. If the locator is
        invalid, an error is generated:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b/&gt;', '/&amp;a');</code></strong>
<span class="errortext">ERROR 1105 (HY000): XPATH syntax error: '&amp;a'</span>
</pre><p>
      If <em class="replaceable"><code>xml_frag</code></em> does not consist of
      elements which are properly nested and closed,
      <code class="literal">NULL</code> is returned and a warning is generated, as
      shown in this example:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b', '//a');</code></strong>
+-----------------------------------+
| ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b', '//a') |
+-----------------------------------+
| NULL                              |
+-----------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS\G</code></strong>
*************************** 1. row ***************************
  Level: Warning
   Code: 1525
Message: Incorrect XML value: 'parse error at line 1 pos 11:
         END-OF-INPUT unexpected ('&gt;' wanted)'
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b/&gt;', '//a');</code></strong>
+-------------------------------------+
| ExtractValue('&lt;a&gt;c&lt;/a&gt;&lt;b/&gt;', '//a') |
+-------------------------------------+
| c                                   |
+-------------------------------------+
1 row in set (0.00 sec)
</pre>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Important
</div>
<p>
        The replacement XML used as the third argument to
        <a class="link" href="functions.html#function_updatexml"><code class="literal">UpdateXML()</code></a> is
        <span class="emphasis"><em>not</em></span> checked to determine whether it
        consists solely of elements which are properly nested and
        closed.
</p>
</div>
<p><b>XPath Injection. </b>
        <span class="firstterm">code injection</span> occurs when
        malicious code is introduced into the system to gain
        unauthorized access to privileges and data. It is based on
        exploiting assumptions made by developers about the type and
        content of data input from users. XPath is no exception in this
        regard.
      </p><p>
      A common scenario in which this can happen is the case of
      application which handles authorization by matching the
      combination of a login name and password with those found in an
      XML file, using an XPath expression like this one:
    </p><pre data-lang="simple" class="programlisting">//user[login/text()='neapolitan' and password/text()='1c3cr34m']/attribute::id</pre><p>
      This is the XPath equivalent of an SQL statement like this one:
    </p><pre data-lang="sql" class="programlisting">SELECT id FROM users WHERE login='neapolitan' AND password='1c3cr34m';</pre><p>
      A PHP application employing XPath might handle the login process
      like this:
    </p><pre data-lang="php" class="programlisting">&lt;?php

  $file     =   "users.xml";

  $login    =   $POST["login"];
  $password =   $POST["password"];

  $xpath = "//user[login/text()=$login and password/text()=$password]/attribute::id";

  if( file_exists($file) )
  {
    $xml = simplexml_load_file($file);

    if($result = $xml-&gt;xpath($xpath))
      echo "You are now logged in as user $result[0].";
    else
      echo "Invalid login name or password.";
  }
  else
    exit("Failed to open $file.");

?&gt;</pre><p>
      No checks are performed on the input. This means that a malevolent
      user can <span class="quote">“<span class="quote">short-circuit</span>”</span> the test by entering
      <code class="literal">' or 1=1</code> for both the login name and password,
      resulting in <code class="varname">$xpath</code> being evaluated as shown
      here:
    </p><pre data-lang="simple" class="programlisting">//user[login/text()='' or 1=1 and password/text()='' or 1=1]/attribute::id</pre><p>
      Since the expression inside the square brackets always evaluates
      as <code class="literal">true</code>, it is effectively the same as this
      one, which matches the <code class="literal">id</code> attribute of every
      <code class="literal">user</code> element in the XML document:
    </p><pre data-lang="simple" class="programlisting">//user/attribute::id</pre><p>
      One way in which this particular attack can be circumvented is
      simply by quoting the variable names to be interpolated in the
      definition of <code class="literal">$xpath</code>, forcing the values passed
      from a Web form to be converted to strings:
    </p><pre data-lang="simple" class="programlisting">$xpath = "//user[login/text()='$login' and password/text()='$password']/attribute::id";</pre><p>
      This is the same strategy that is often recommended for preventing
      SQL injection attacks. In general, the practices you should follow
      for preventing XPath injection attacks are the same as for
      preventing SQL injection:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Never accepted untested data from users in your application.
        </p></li><li class="listitem"><p>
          Check all user-submitted data for type; reject or convert data
          that is of the wrong type
        </p></li><li class="listitem"><p>
          Test numeric data for out of range values; truncate, round, or
          reject values that are out of range. Test strings for illegal
          characters and either strip them out or reject input
          containing them.
        </p></li><li class="listitem"><p>
          Do not output explicit error messages that might provide an
          unauthorized user with clues that could be used to compromise
          the system; log these to a file or database table instead.
</p></li></ul>
</div>
<p>
      Just as SQL injection attacks can be used to obtain information
      about database schemas, so can XPath injection be used to traverse
      XML files to uncover their structure, as discussed in Amit
      Klein's paper
      <a class="ulink" href="http://www.packetstormsecurity.org/papers/bypass/Blind_XPath_Injection_20040518.pdf" target="_top">Blind
      XPath Injection</a> (PDF file, 46KB).
    </p><p>
      It is also important to check the output being sent back to the
      client. Consider what can happen when we use the MySQL
      <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a> function:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ExtractValue(</code></strong>
    -&gt;     <strong class="userinput"><code>LOAD_FILE('users.xml'),</code></strong>
    -&gt;     <strong class="userinput"><code>'//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'</code></strong>
    -&gt; <strong class="userinput"><code>) AS id;</code></strong>
+-------------------------------+
| id                            |
+-------------------------------+
| 00327 13579 02403 42354 28570 |
+-------------------------------+
1 row in set (0.01 sec)
</pre><p>
      Because <a class="link" href="functions.html#function_extractvalue"><code class="literal">ExtractValue()</code></a> returns
      multiple matches as a single space-delimited string, this
      injection attack provides every valid ID contained within
      <code class="filename">users.xml</code> to the user as a single row of
      output. As an extra safeguard, you should also test output before
      returning it to the user. Here is a simple example:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT @id = ExtractValue(</code></strong>
    -&gt;     <strong class="userinput"><code>LOAD_FILE('users.xml'),</code></strong>
    -&gt;     <strong class="userinput"><code>'//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'</code></strong>
    -&gt; <strong class="userinput"><code>);</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT IF(</code></strong>
    -&gt;     <strong class="userinput"><code>INSTR(@id, ' ') = 0,</code></strong>
    -&gt;     <strong class="userinput"><code>@id,</code></strong>
    -&gt;     <strong class="userinput"><code>'Unable to retrieve user ID')</code></strong>
    -&gt; <strong class="userinput"><code>AS singleID;</code></strong>
+----------------------------+
| singleID                   |
+----------------------------+
| Unable to retrieve user ID |
+----------------------------+
1 row in set (0.00 sec)
</pre><p>
      In general, the guidelines for returning data to users securely
      are the same as for accepting user input. These can be summed up
      as:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Always test outgoing data for type and permissible values.
        </p></li><li class="listitem"><p>
          Never permit unauthorized users to view error messages that
          might provide information about the application that could be
          used to exploit it.
</p></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="bit-functions"></a>12.12 Bit Functions and Operators</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444325846672"></a><a class="indexterm" name="idm46444325845216"></a><a class="indexterm" name="idm46444325843728"></a><a class="indexterm" name="idm46444325842656"></a><a class="indexterm" name="idm46444325841584"></a><a class="indexterm" name="idm46444325840080"></a><a class="indexterm" name="idm46444325838624"></a><a class="indexterm" name="idm46444325837552"></a>
<div class="table">
<a name="idm46444325836480"></a><p class="title"><b>Table 12.16 Bit Functions and Operators</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists bit functions and operators."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a></td>
<td>
      Bitwise AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_right-shift"><code class="literal">&gt;&gt;</code></a></td>
<td>
      Right shift
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_left-shift"><code class="literal">&lt;&lt;</code></a></td>
<td>
      Left shift
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-xor"><code class="literal">^</code></a></td>
<td>
      Bitwise XOR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-count"><code class="literal">BIT_COUNT()</code></a></td>
<td>
      Return the number of bits that are set
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-or"><code class="literal">|</code></a></td>
<td>
      Bitwise OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a></td>
<td>
      Bitwise inversion
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      Bit functions and operators comprise
      <a class="link" href="functions.html#function_bit-count"><code class="literal">BIT_COUNT()</code></a>,
      <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a>,
      <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a>,
      <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a>,
      <a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a>,
      <a class="link" href="functions.html#operator_bitwise-or"><code class="literal">|</code></a>,
      <a class="link" href="functions.html#operator_bitwise-xor"><code class="literal">^</code></a>,
      <a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a>,
      <a class="link" href="functions.html#operator_left-shift"><code class="literal">&lt;&lt;</code></a>, and
      <a class="link" href="functions.html#operator_right-shift"><code class="literal">&gt;&gt;</code></a>.
      (The <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a>,
      <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a>, and
      <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a> aggregate functions are
      described in <a class="xref" href="functions.html#group-by-functions" title="12.20.1 Aggregate (GROUP BY) Function Descriptions">Section 12.20.1, “Aggregate (GROUP BY) Function Descriptions”</a>.) Prior to MySQL
      8.0, bit functions and operators required
      <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> (64-bit integer) arguments
      and returned <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> values, so they
      had a maximum range of 64 bits.
      Non-<a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> arguments were converted
      to <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> prior to performing the
      operation and truncation could occur.
    </p><p>
      In MySQL 8.0, bit functions and operators permit
      binary string type arguments
      (<a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
      <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>, and the
      <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> types) and return a value of
      like type, which enables them to take arguments and produce return
      values larger than 64 bits. Nonbinary string arguments are
      converted to <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> and processed
      as such, as before.
    </p><p>
      An implication of this change in behavior is that bit operations
      on binary string arguments might produce a different result in
      MySQL 8.0 than in 5.7. For information
      about how to prepare in MySQL 5.7 for potential
      incompatibilities between MySQL 5.7 and 8.0, see
      <a class="ulink" href="https://dev.mysql.com/doc/refman/5.7/en/bit-functions.html" target="_top">Bit Functions and Operators</a>, in
      <a class="ulink" href="https://dev.mysql.com/doc/refman/5.7/en/" target="_top">MySQL 5.7 Reference Manual</a>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-5-7" title="Bit Operations Prior to MySQL 8.0">Bit Operations Prior to MySQL 8.0</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-8-0" title="Bit Operations in MySQL 8.0">Bit Operations in MySQL 8.0</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-binary-string-examples" title="Binary String Bit-Operation Examples">Binary String Bit-Operation Examples</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-and-or-xor" title="Bitwise AND, OR, and XOR Operations">Bitwise AND, OR, and XOR Operations</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-complement-shift" title="Bitwise Complement and Shift Operations">Bitwise Complement and Shift Operations</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-bit-count" title="BIT_COUNT() Operations">BIT_COUNT() Operations</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-bit-aggregate" title="BIT_AND(), BIT_OR(), and BIT_XOR() Operations">BIT_AND(), BIT_OR(), and BIT_XOR() Operations</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-literal-handling" title="Special Handling of Hexadecimal Literals, Bit Literals, and NULL Literals">Special Handling of Hexadecimal Literals, Bit Literals, and NULL
Literals</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#bit-operations-incompatibilities" title="Bit-Operation Incompatibilities with MySQL 5.7">Bit-Operation Incompatibilities with MySQL 5.7</a></p></li></ul>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-5-7"></a>Bit Operations Prior to MySQL 8.0</h3>

</div>

</div>

</div>
<p>
        Bit operations prior to MySQL 8.0 handle only unsigned 64-bit
        integer argument and result values (that is, unsigned
        <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> values). Conversion of
        arguments of other types to
        <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> occurs as necessary.
        Examples:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            This statement operates on numeric literals, treated as
            unsigned 64-bit integers:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 127 | 128, 128 &lt;&lt; 2, BIT_COUNT(15);</code></strong>
+-----------+----------+---------------+
| 127 | 128 | 128 &lt;&lt; 2 | BIT_COUNT(15) |
+-----------+----------+---------------+
|       255 |      512 |             4 |
+-----------+----------+---------------+
</pre></li><li class="listitem"><p>
            This statement performs to-number conversions on the string
            arguments (<code class="literal">'127'</code> to
            <code class="literal">127</code>, and so forth) before performing the
            same operations as the first statement and producing the
            same results:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT '127' | '128', '128' &lt;&lt; 2, BIT_COUNT('15');</code></strong>
+---------------+------------+-----------------+
| '127' | '128' | '128' &lt;&lt; 2 | BIT_COUNT('15') |
+---------------+------------+-----------------+
|           255 |        512 |               4 |
+---------------+------------+-----------------+
</pre></li><li class="listitem"><p>
            This statement uses hexadecimal literals for the
            bit-operation arguments. MySQL by default treats hexadecimal
            literals as binary strings, but in numeric context evaluates
            them as numbers (see
            <a class="xref" href="language-structure.html#hexadecimal-literals" title="9.1.4 Hexadecimal Literals">Section 9.1.4, “Hexadecimal Literals”</a>). Prior to MySQL 8.0,
            numeric context includes bit operations. Examples:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT X'7F' | X'80', X'80' &lt;&lt; 2, BIT_COUNT(X'0F');</code></strong>
+---------------+------------+------------------+
| X'7F' | X'80' | X'80' &lt;&lt; 2 | BIT_COUNT(X'0F') |
+---------------+------------+------------------+
|           255 |        512 |                4 |
+---------------+------------+------------------+
</pre><p>
            Handling of bit-value literals in bit operations is similar
            to hexadecimal literals (that is, as numbers).
</p></li></ul>
</div>

</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-8-0"></a>Bit Operations in MySQL 8.0</h3>

</div>

</div>

</div>
<p>
        MySQL 8.0 extends bit operations to handle binary string
        arguments directly (without conversion) and produce binary
        string results. (Arguments that are not integers or binary
        strings are still converted to integers, as before.) This
        extension enhances bit operations in the following ways:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Bit operations become possible on values longer than 64
            bits.
          </p></li><li class="listitem"><p>
            It is easier to perform bit operations on values that are
            more naturally represented as binary strings than as
            integers.
</p></li></ul>
</div>
<p>
        For example, consider UUID values and IPv6 addresses, which have
        human-readable text formats like this:
      </p><pre data-lang="none" class="programlisting">UUID: 6ccd780c-baba-1026-9564-5b8c656024db
IPv6: fe80::219:d1ff:fe91:1a72</pre><p>
        It is cumbersome to operate on text strings in those formats. An
        alternative is convert them to fixed-length binary strings
        without delimiters. <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a>
        and <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a> each produce a
        value of data type <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY(16)</code></a>, a
        binary string 16 bytes (128 bits) long. The following statements
        illustrate this (<code class="literal">HEX()</code> is used to produce
        displayable values):
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(UUID_TO_BIN('6ccd780c-baba-1026-9564-5b8c656024db'));</code></strong>
+----------------------------------------------------------+
| HEX(UUID_TO_BIN('6ccd780c-baba-1026-9564-5b8c656024db')) |
+----------------------------------------------------------+
| 6CCD780CBABA102695645B8C656024DB                         |
+----------------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT HEX(INET6_ATON('fe80::219:d1ff:fe91:1a72'));</code></strong>
+---------------------------------------------+
| HEX(INET6_ATON('fe80::219:d1ff:fe91:1a72')) |
+---------------------------------------------+
| FE800000000000000219D1FFFE911A72            |
+---------------------------------------------+
</pre><p>
        Those binary values are easily manipulable with bit operations
        to perform actions such as extracting the timestamp from UUID
        values, or extracting the network and host parts of IPv6
        addresses. (For examples, see later in this discussion.)
      </p><p>
        Arguments that count as binary strings include column values,
        routine parameters, local variables, and user-defined variables
        that have a binary string type:
        <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
        <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>, or one of the
        <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> types.
      </p><p>
        What about hexadecimal literals and bit literals? Recall that
        those are binary strings by default in MySQL, but numbers in
        numeric context. How are they handled for bit operations in
        MySQL 8.0? Does MySQL continue to evaluate them in numeric
        context, as is done prior to MySQL 8.0? Or do bit operations
        evaluate them as binary strings, now that binary strings can be
        handled <span class="quote">“<span class="quote">natively</span>”</span> without conversion?
      </p><p>
        Answer: It has been common to specify arguments to bit
        operations using hexadecimal literals or bit literals with the
        intent that they represent numbers, so MySQL continues to
        evaluate bit operations in numeric context when all bit
        arguments are hexadecimal or bit literals, for backward
        compatility. If you require evaluation as binary strings
        instead, that is easily accomplished: Use the
        <code class="literal">_binary</code> introducer for at least one literal.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            These bit operations evaluate the hexadecimal literals and
            bit literals as integers:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT X'40' | X'01', b'11110001' &amp; b'01001111';</code></strong>
+---------------+---------------------------+
| X'40' | X'01' | b'11110001' &amp; b'01001111' |
+---------------+---------------------------+
|            65 |                        65 |
+---------------+---------------------------+
</pre></li><li class="listitem"><p>
            These bit operations evaluate the hexadecimal literals and
            bit literals as binary strings, due to the
            <code class="literal">_binary</code> introducer:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT _binary X'40' | X'01', b'11110001' &amp; _binary b'01001111';</code></strong>
+-----------------------+-----------------------------------+
| _binary X'40' | X'01' | b'11110001' &amp; _binary b'01001111' |
+-----------------------+-----------------------------------+
| A                     | A                                 |
+-----------------------+-----------------------------------+
</pre></li></ul>
</div>
<p>
        Although the bit operations in both statements produce a result
        with a numeric value of 65, the second statement operates in
        binary-string context, for which 65 is ASCII
        <code class="literal">A</code>.
      </p><p>
        In numeric evaluation context, permitted values of hexadecimal
        literal and bit literal arguments have a maximum of 64 bits, as
        do results. By contrast, in binary-string evaluation context,
        permitted arguments (and results) can exceed 64 bits:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT _binary X'4040404040404040' | X'0102030405060708';</code></strong>
+---------------------------------------------------+
| _binary X'4040404040404040' | X'0102030405060708' |
+---------------------------------------------------+
| ABCDEFGH                                          |
+---------------------------------------------------+
</pre><p>
        There are several ways to refer to a hexadecimal literal or bit
        literal in a bit operation to cause binary-string evaluation:
      </p><pre data-lang="sql" class="programlisting">_binary <em class="replaceable"><code>literal</code></em>
BINARY <em class="replaceable"><code>literal</code></em>
CAST(<em class="replaceable"><code>literal</code></em> AS BINARY)
</pre><p>
        Another way to produce binary-string evaluation of hexadecimal
        literals or bit literals is to assign them to user-defined
        variables, which results in variables that have a binary string
        type:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @v1 = X'40', @v2 = X'01', @v3 = b'11110001', @v4 = b'01001111';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @v1 | @v2, @v3 &amp; @v4;</code></strong>
+-----------+-----------+
| @v1 | @v2 | @v3 &amp; @v4 |
+-----------+-----------+
| A         | A         |
+-----------+-----------+
</pre><p>
        In binary-string context, bitwise operation arguments must have
        the same length or an
        <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
        error occurs:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT _binary X'40' | X'0001';</code></strong>
ERROR 3513 (HY000): Binary operands of bitwise
operators must be of equal length
</pre><p>
        To satisfy the equal-length requirement, pad the shorter value
        with leading zero digits or, if the longer value begins with
        leading zero digits and a shorter result value is acceptable,
        strip them:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT _binary X'0040' | X'0001';</code></strong>
+---------------------------+
| _binary X'0040' | X'0001' |
+---------------------------+
|  A                        |
+---------------------------+
mysql&gt; <strong class="userinput"><code>SELECT _binary X'40' | X'01';</code></strong>
+-----------------------+
| _binary X'40' | X'01' |
+-----------------------+
| A                     |
+-----------------------+
</pre><p>
        Padding or stripping can also be accomplished using functions
        such as <a class="link" href="functions.html#function_lpad"><code class="literal">LPAD()</code></a>,
        <a class="link" href="functions.html#function_rpad"><code class="literal">RPAD()</code></a>,
        <a class="link" href="functions.html#function_substr"><code class="literal">SUBSTR()</code></a>, or
        <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a>. In such cases, the
        expression arguments are no longer all literals and
        <code class="literal">_binary</code> becomes unnecessary. Examples:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LPAD(X'40', 2, X'00') | X'0001';</code></strong>
+---------------------------------+
| LPAD(X'40', 2, X'00') | X'0001' |
+---------------------------------+
|  A                              |
+---------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT X'40' | SUBSTR(X'0001', 2, 1);</code></strong>
+-------------------------------+
| X'40' | SUBSTR(X'0001', 2, 1) |
+-------------------------------+
| A                             |
+-------------------------------+
</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-binary-string-examples"></a>Binary String Bit-Operation Examples</h3>

</div>

</div>

</div>
<p>
        The following example illustrates use of bit operations to
        extract parts of a UUID value, in this case, the timestamp and
        IEEE 802 node number. This technique requires bitmasks for each
        extracted part.
      </p><p>
        Convert the text UUID to the corresponding 16-byte binary value
        so that it can be manipulated using bit operations in
        binary-string context:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @uuid = UUID_TO_BIN('6ccd780c-baba-1026-9564-5b8c656024db');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT HEX(@uuid);</code></strong>
+----------------------------------+
| HEX(@uuid)                       |
+----------------------------------+
| 6CCD780CBABA102695645B8C656024DB |
+----------------------------------+
</pre><p>
        Construct bitmasks for the timestamp and node number parts of
        the value. The timestamp comprises the first three parts (64
        bits, bits 0 to 63) and the node number is the last part (48
        bits, bits 80 to 127):
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ts_mask = CAST(X'FFFFFFFFFFFFFFFF' AS BINARY(16));</code></strong>
mysql&gt; <strong class="userinput"><code>SET @node_mask = CAST(X'FFFFFFFFFFFF' AS BINARY(16)) &gt;&gt; 80;</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT HEX(@ts_mask);</code></strong>
+----------------------------------+
| HEX(@ts_mask)                    |
+----------------------------------+
| FFFFFFFFFFFFFFFF0000000000000000 |
+----------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT HEX(@node_mask);</code></strong>
+----------------------------------+
| HEX(@node_mask)                  |
+----------------------------------+
| 00000000000000000000FFFFFFFFFFFF |
+----------------------------------+
</pre><p>
        The <code class="literal">CAST(... AS BINARY(16))</code> function is used
        here because the masks must be the same length as the UUID value
        against which they are applied. The same result can be produced
        using other functions to pad the masks to the required length:
      </p><pre data-lang="sql" class="programlisting">SET @ts_mask= RPAD(X'FFFFFFFFFFFFFFFF' , 16, X'00');
SET @node_mask = LPAD(X'FFFFFFFFFFFF', 16, X'00') ;</pre><p>
        Use the masks to extract the timestamp and node number parts:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(@uuid &amp; @ts_mask) AS 'timestamp part';</code></strong>
+----------------------------------+
| timestamp part                   |
+----------------------------------+
| 6CCD780CBABA10260000000000000000 |
+----------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT HEX(@uuid &amp; @node_mask) AS 'node part';</code></strong>
+----------------------------------+
| node part                        |
+----------------------------------+
| 000000000000000000005B8C656024DB |
+----------------------------------+
</pre><p>
        The preceding example uses these bit operations: right shift
        (<a class="link" href="functions.html#operator_right-shift"><code class="literal">&gt;&gt;</code></a>)
        and bitwise AND
        (<a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a>).
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a> takes a flag that
          causes some bit rearrangement in the resulting binary UUID
          value. If you use that flag, modify the extraction masks
          accordingly.
</p>
</div>
<p>
        The next example uses bit operations to extract the network and
        host parts of an IPv6 address. Suppose that the network part has
        a length of 80 bits. Then the host part has a length of 128
        − 80 = 48 bits. To extract the network and host parts of
        the address, convert it to a binary string, then use bit
        operations in binary-string context.
      </p><p>
        Convert the text IPv6 address to the corresponding binary
        string:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ip = INET6_ATON('fe80::219:d1ff:fe91:1a72');</code></strong>
</pre><p>
        Define the network length in bits:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @net_len = 80;</code></strong>
</pre><p>
        Construct network and host masks by shifting the all-ones
        address left or right. To do this, begin with the address
        <code class="literal">::</code>, which is shorthand for all zeros, as you
        can see by converting it to a binary string like this:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(INET6_ATON('::')) AS 'all zeros';</code></strong>
+----------------------------------+
| all zeros                        |
+----------------------------------+
| 00000000000000000000000000000000 |
+----------------------------------+
</pre><p>
        To produce the complementary value (all ones), use the
        <a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a>
        operator to invert the bits:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(~INET6_ATON('::')) AS 'all ones';</code></strong>
+----------------------------------+
| all ones                         |
+----------------------------------+
| FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
+----------------------------------+
</pre><p>
        Shift the all-ones value left or right to produce the network
        and host masks:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @net_mask = ~INET6_ATON('::') &lt;&lt; (128 - @net_len);</code></strong>
mysql&gt; <strong class="userinput"><code>SET @host_mask = ~INET6_ATON('::') &gt;&gt; @net_len;</code></strong>
</pre><p>
        Display the masks to verify that they cover the correct parts of
        the address:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(@net_mask) AS 'network mask';</code></strong>
+----------------------------+
| network mask               |
+----------------------------+
| ffff:ffff:ffff:ffff:ffff:: |
+----------------------------+
mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(@host_mask) AS 'host mask';</code></strong>
+------------------------+
| host mask              |
+------------------------+
| ::ffff:255.255.255.255 |
+------------------------+
</pre><p>
        Extract and display the network and host parts of the address:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @net_part = @ip &amp; @net_mask;</code></strong>
mysql&gt; <strong class="userinput"><code>SET @host_part = @ip &amp; @host_mask;</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(@net_part) AS 'network part';</code></strong>
+-----------------+
| network part    |
+-----------------+
| fe80::219:0:0:0 |
+-----------------+
mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(@host_part) AS 'host part';</code></strong>
+------------------+
| host part        |
+------------------+
| ::d1ff:fe91:1a72 |
+------------------+
</pre><p>
        The preceding example uses these bit operations: Complement
        (<a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a>),
        left shift
        (<a class="link" href="functions.html#operator_left-shift"><code class="literal">&lt;&lt;</code></a>),
        and bitwise AND
        (<a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a>).
      </p><p>
        The remaining discussion provides details on argument handling
        for each group of bit operations, more information about
        literal-value handling in bit operations, and potential
        incompatibilities between MySQL 8.0 and older MySQL versions.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-and-or-xor"></a>Bitwise AND, OR, and XOR Operations</h3>

</div>

</div>

</div>
<p>
        For <a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a>,
        <a class="link" href="functions.html#operator_bitwise-or"><code class="literal">|</code></a>, and
        <a class="link" href="functions.html#operator_bitwise-xor"><code class="literal">^</code></a> bit
        operations, the result type depends on whether the arguments are
        evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Binary-string evaluation occurs when the arguments have a
            binary string type, and at least one of them is not a
            hexadecimal literal, bit literal, or <code class="literal">NULL</code>
            literal. Numeric evaluation occurs otherwise, with argument
            conversion to unsigned 64-bit integers as necessary.
          </p></li><li class="listitem"><p>
            Binary-string evaluation produces a binary string of the
            same length as the arguments. If the arguments have unequal
            lengths, an
            <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
            error occurs. Numeric evaluation produces an unsigned 64-bit
            integer.
</p></li></ul>
</div>
<p>
        Examples of numeric evaluation:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 64 | 1, X'40' | X'01';</code></strong>
+--------+---------------+
| 64 | 1 | X'40' | X'01' |
+--------+---------------+
|     65 |            65 |
+--------+---------------+
</pre><p>
        Examples of binary-string evaluation:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT _binary X'40' | X'01';</code></strong>
+-----------------------+
| _binary X'40' | X'01' |
+-----------------------+
| A                     |
+-----------------------+
mysql&gt; <strong class="userinput"><code>SET @var1 = X'40', @var2 = X'01';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @var1 | @var2;</code></strong>
+---------------+
| @var1 | @var2 |
+---------------+
| A             |
+---------------+
</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-complement-shift"></a>Bitwise Complement and Shift Operations</h3>

</div>

</div>

</div>
<p>
        For <a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a>,
        <a class="link" href="functions.html#operator_left-shift"><code class="literal">&lt;&lt;</code></a>,
        and
        <a class="link" href="functions.html#operator_right-shift"><code class="literal">&gt;&gt;</code></a>
        bit operations, the result type depends on whether the bit
        argument is evaluated as a binary string or number:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Binary-string evaluation occurs when the bit argument has a
            binary string type, and is not a hexadecimal literal, bit
            literal, or <code class="literal">NULL</code> literal. Numeric
            evaluation occurs otherwise, with argument conversion to an
            unsigned 64-bit integer as necessary.
          </p></li><li class="listitem"><p>
            Binary-string evaluation produces a binary string of the
            same length as the bit argument. Numeric evaluation produces
            an unsigned 64-bit integer.
</p></li></ul>
</div>
<p>
        For shift operations, bits shifted off the end of the value are
        lost without warning, regardless of the argument type. In
        particular, if the shift count is greater or equal to the number
        of bits in the bit argument, all bits in the result are 0.
      </p><p>
        Examples of numeric evaluation:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ~0, 64 &lt;&lt; 2, X'40' &lt;&lt; 2;</code></strong>
+----------------------+---------+------------+
| ~0                   | 64 &lt;&lt; 2 | X'40' &lt;&lt; 2 |
+----------------------+---------+------------+
| 18446744073709551615 |     256 |        256 |
+----------------------+---------+------------+
</pre><p>
        Examples of binary-string evaluation:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(_binary X'1111000022220000' &gt;&gt; 16);</code></strong>
+----------------------------------------+
| HEX(_binary X'1111000022220000' &gt;&gt; 16) |
+----------------------------------------+
| 0000111100002222                       |
+----------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT HEX(_binary X'1111000022220000' &lt;&lt; 16);</code></strong>
+----------------------------------------+
| HEX(_binary X'1111000022220000' &lt;&lt; 16) |
+----------------------------------------+
| 0000222200000000                       |
+----------------------------------------+
mysql&gt; <strong class="userinput"><code>SET @var1 = X'F0F0F0F0';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT HEX(~@var1);</code></strong>
+-------------+
| HEX(~@var1) |
+-------------+
| 0F0F0F0F    |
+-------------+
</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-bit-count"></a>BIT_COUNT() Operations</h3>

</div>

</div>

</div>
<p>
        The <a class="link" href="functions.html#function_bit-count"><code class="literal">BIT_COUNT()</code></a> function always
        returns an unsigned 64-bit integer, or <code class="literal">NULL</code>
        if the argument is <code class="literal">NULL</code>.
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT BIT_COUNT(127);</code></strong>
+----------------+
| BIT_COUNT(127) |
+----------------+
|              7 |
+----------------+
mysql&gt; <strong class="userinput"><code>SELECT BIT_COUNT(b'010101'), BIT_COUNT(_binary b'010101');</code></strong>
+----------------------+------------------------------+
| BIT_COUNT(b'010101') | BIT_COUNT(_binary b'010101') |
+----------------------+------------------------------+
|                    3 |                            3 |
+----------------------+------------------------------+
</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-bit-aggregate"></a>BIT_AND(), BIT_OR(), and BIT_XOR() Operations</h3>

</div>

</div>

</div>
<p>
        For the <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a>,
        <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a>, and
        <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a> bit functions, the
        result type depends on whether the function argument values are
        evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Binary-string evaluation occurs when the argument values
            have a binary string type, and the argument is not a
            hexadecimal literal, bit literal, or <code class="literal">NULL</code>
            literal. Numeric evaluation occurs otherwise, with argument
            value conversion to unsigned 64-bit integers as necessary.
          </p></li><li class="listitem"><p>
            Binary-string evaluation produces a binary string of the
            same length as the argument values. If argument values have
            unequal lengths, an
            <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
            error occurs. If the argument size exceeds 511 bytes, an
            <a class="link" href="error-handling.html#error_er_invalid_bitwise_aggregate_operands_size"><code class="literal">ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE</code></a>
            error occurs. Numeric evaluation produces an unsigned 64-bit
            integer.
</p></li></ul>
</div>
<p>
        <code class="literal">NULL</code> values do not affect the result unless
        all values are <code class="literal">NULL</code>. In that case, the result
        is a neutral value having the same length as the length of the
        argument values (all bits 1 for
        <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a>, all bits 0 for
        <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a>, and
        <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a>).
      </p><p>
        Example:
      </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>CREATE TABLE t (group_id INT, a VARBINARY(6));</code></strong>
mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES (1, NULL);</code></strong>
mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES (1, NULL);</code></strong>
mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES (2, NULL);</code></strong>
mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES (2, X'1234');</code></strong>
mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES (2, X'FF34');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT HEX(BIT_AND(a)), HEX(BIT_OR(a)), HEX(BIT_XOR(a))</code></strong>
       <strong class="userinput"><code>FROM t GROUP BY group_id;</code></strong>
+-----------------+----------------+-----------------+
| HEX(BIT_AND(a)) | HEX(BIT_OR(a)) | HEX(BIT_XOR(a)) |
+-----------------+----------------+-----------------+
| FFFFFFFFFFFF    | 000000000000   | 000000000000    |
| 1234            | FF34           | ED00            |
+-----------------+----------------+-----------------+
</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-literal-handling"></a>Special Handling of Hexadecimal Literals, Bit Literals, and NULL
Literals</h3>
</div>
</div>
</div>
<p>
        For backward compatibility, MySQL 8.0 evaluates bit operations
        in numeric context when all bit arguments are hexadecimal
        literals, bit literals, or <code class="literal">NULL</code> literals.
        That is, bit operations on binary-string bit arguments do not
        use binary-string evaluation if all bit arguments are unadorned
        hexadecimal literals, bit literals, or <code class="literal">NULL</code>
        literals. (This does not apply to such literals if they are
        written with a <code class="literal">_binary</code> introducer,
        <a class="link" href="functions.html#operator_binary"><code class="literal">BINARY</code></a> operator, or other way of
        specifying them explicitly as binary strings.)
      </p><p>
        The literal handling just described is the same as prior to
        MySQL 8.0. Examples:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            These bit operations evaluate the literals in numeric
            context and produce a <code class="literal">BIGINT</code> result:
          </p><pre data-lang="sql" class="programlisting">b'0001' | b'0010'
X'0008' &lt;&lt; 8</pre></li><li class="listitem"><p>
            These bit operations evaluate <code class="literal">NULL</code> in
            numeric context and produce a <code class="literal">BIGINT</code>
            result that has a <code class="literal">NULL</code> value:
          </p><pre data-lang="sql" class="programlisting">NULL &amp; NULL
NULL &gt;&gt; 4</pre></li></ul>
</div>
<p>
        In MySQL 8.0, you can cause those operations to evaluate the
        arguments in binary-string context by indicating explicitly that
        at least one argument is a binary string:
      </p><pre data-lang="sql" class="programlisting">_binary b'0001' | b'0010'
_binary X'0008' &lt;&lt; 8
BINARY NULL &amp; NULL
BINARY NULL &gt;&gt; 4</pre><p>
        The result of the last two expressions is
        <code class="literal">NULL</code>, just as without the
        <code class="literal">BINARY</code> operator, but the data type of the
        result is a binary string type rather than an integer type.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h3 class="title"><a name="bit-operations-incompatibilities"></a>Bit-Operation Incompatibilities with MySQL 5.7</h3>

</div>

</div>

</div>
<p>
        Because bit operations can handle binary string arguments
        natively in MySQL 8.0, some expressions produce a different
        result in MySQL 8.0 than in 5.7. The five problematic expression
        types to watch out for are:
      </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>nonliteral_binary</code></em> { &amp; | ^ } <em class="replaceable"><code>binary</code></em>
<em class="replaceable"><code>binary</code></em>  { &amp; | ^ } <em class="replaceable"><code>nonliteral_binary</code></em>
<em class="replaceable"><code>nonliteral_binary</code></em> { &lt;&lt; &gt;&gt; } <em class="replaceable"><code>anything</code></em>
~ <em class="replaceable"><code>nonliteral_binary</code></em>
<em class="replaceable"><code>AGGR_BIT_FUNC</code></em>(<em class="replaceable"><code>nonliteral_binary</code></em>)
</pre><p>
        Those expressions return <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>
        in MySQL 5.7, binary string in 8.0.
      </p><p>
        Explanation of notation:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <code class="literal">{ <em class="replaceable"><code>op1</code></em>
            <em class="replaceable"><code>op2</code></em> ... }</code>: List of
            operators that apply to the given expression type.
          </p></li><li class="listitem"><p>
            <em class="replaceable"><code>binary</code></em>: Any kind of binary string
            argument, including a hexadecimal literal, bit literal, or
            <code class="literal">NULL</code> literal.
          </p></li><li class="listitem"><p>
            <em class="replaceable"><code>nonliteral_binary</code></em>: An argument
            that is a binary string value other than a hexadecimal
            literal, bit literal, or <code class="literal">NULL</code> literal.
          </p></li><li class="listitem"><p>
            <em class="replaceable"><code>AGGR_BIT_FUNC</code></em>: An aggregate
            function that takes bit-value arguments:
            <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a>,
            <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a>,
            <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a>.
</p></li></ul>
</div>
<p>
        For information about how to prepare in MySQL 5.7 for potential
        incompatibilities between MySQL 5.7 and 8.0, see
        <a class="ulink" href="https://dev.mysql.com/doc/refman/5.7/en/bit-functions.html" target="_top">Bit Functions and Operators</a>, in
        <a class="ulink" href="https://dev.mysql.com/doc/refman/5.7/en/" target="_top">MySQL 5.7 Reference Manual</a>.
      </p><p>
        The following list describes available bit functions and
        operators:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="operator_bitwise-or"></a><p>
            <a class="indexterm" name="idm46444325535456"></a>

            <a class="indexterm" name="idm46444325534384"></a>

            <a class="link" href="functions.html#operator_bitwise-or"><code class="literal">|</code></a>
          </p><p>
            Bitwise OR.
          </p><p>
            The result type depends on whether the arguments are
            evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the arguments have
                a binary string type, and at least one of them is not a
                hexadecimal literal, bit literal, or
                <code class="literal">NULL</code> literal. Numeric evaluation
                occurs otherwise, with argument conversion to unsigned
                64-bit integers as necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the arguments. If the arguments have
                unequal lengths, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
                error occurs. Numeric evaluation produces an unsigned
                64-bit integer.
</p></li></ul>
</div>
<p>
            For more information, see the introductory discussion in
            this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 29 | 15;</code></strong>
        -&gt; 31
mysql&gt; <strong class="userinput"><code>SELECT _binary X'40404040' | X'01020304';</code></strong>
        -&gt; 'ABCD'
</pre></li><li class="listitem"><a name="operator_bitwise-and"></a><p>
            <a class="indexterm" name="idm46444325518656"></a>

            <a class="indexterm" name="idm46444325517568"></a>

            <a class="link" href="functions.html#operator_bitwise-and"><code class="literal">&amp;</code></a>
          </p><p>
            Bitwise AND.
          </p><p>
            The result type depends on whether the arguments are
            evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the arguments have
                a binary string type, and at least one of them is not a
                hexadecimal literal, bit literal, or
                <code class="literal">NULL</code> literal. Numeric evaluation
                occurs otherwise, with argument conversion to unsigned
                64-bit integers as necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the arguments. If the arguments have
                unequal lengths, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
                error occurs. Numeric evaluation produces an unsigned
                64-bit integer.
</p></li></ul>
</div>
<p>
            For more information, see the introductory discussion in
            this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 29 &amp; 15;</code></strong>
        -&gt; 13
mysql&gt; <strong class="userinput"><code>SELECT HEX(_binary X'FF' &amp; b'11110000');</code></strong>
        -&gt; 'F0'
</pre></li><li class="listitem"><a name="operator_bitwise-xor"></a><p>
            <a class="indexterm" name="idm46444325501904"></a>

            <a class="indexterm" name="idm46444325500832"></a>

            <a class="link" href="functions.html#operator_bitwise-xor"><code class="literal">^</code></a>
          </p><p>
            Bitwise XOR.
          </p><p>
            The result type depends on whether the arguments are
            evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the arguments have
                a binary string type, and at least one of them is not a
                hexadecimal literal, bit literal, or
                <code class="literal">NULL</code> literal. Numeric evaluation
                occurs otherwise, with argument conversion to unsigned
                64-bit integers as necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the arguments. If the arguments have
                unequal lengths, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
                error occurs. Numeric evaluation produces an unsigned
                64-bit integer.
</p></li></ul>
</div>
<p>
            For more information, see the introductory discussion in
            this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 ^ 1;</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT 1 ^ 0;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT 11 ^ 3;</code></strong>
        -&gt; 8
mysql&gt; <strong class="userinput"><code>SELECT HEX(_binary X'FEDC' ^ X'1111');</code></strong>
        -&gt; 'EFCD'
</pre></li><li class="listitem"><a name="operator_left-shift"></a><p>
            <a class="indexterm" name="idm46444325483680"></a>

            <a class="link" href="functions.html#operator_left-shift"><code class="literal">&lt;&lt;</code></a>
          </p><p>
            Shifts a longlong (<a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>)
            number or binary string to the left.
          </p><p>
            The result type depends on whether the bit argument is
            evaluated as a binary string or number:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the bit argument
                has a binary string type, and is not a hexadecimal
                literal, bit literal, or <code class="literal">NULL</code>
                literal. Numeric evaluation occurs otherwise, with
                argument conversion to an unsigned 64-bit integer as
                necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the bit argument. Numeric evaluation
                produces an unsigned 64-bit integer.
</p></li></ul>
</div>
<p>
            Bits shifted off the end of the value are lost without
            warning, regardless of the argument type. In particular, if
            the shift count is greater or equal to the number of bits in
            the bit argument, all bits in the result are 0.
          </p><p>
            For more information, see the introductory discussion in
            this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 &lt;&lt; 2;</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT HEX(_binary X'00FF00FF00FF' &lt;&lt; 8);</code></strong>
        -&gt; 'FF00FF00FF00'
</pre></li><li class="listitem"><a name="operator_right-shift"></a><p>
            <a class="indexterm" name="idm46444325467600"></a>

            <a class="link" href="functions.html#operator_right-shift"><code class="literal">&gt;&gt;</code></a>
          </p><p>
            Shifts a longlong (<a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a>)
            number or binary string to the right.
          </p><p>
            The result type depends on whether the bit argument is
            evaluated as a binary string or number:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the bit argument
                has a binary string type, and is not a hexadecimal
                literal, bit literal, or <code class="literal">NULL</code>
                literal. Numeric evaluation occurs otherwise, with
                argument conversion to an unsigned 64-bit integer as
                necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the bit argument. Numeric evaluation
                produces an unsigned 64-bit integer.
</p></li></ul>
</div>
<p>
            Bits shifted off the end of the value are lost without
            warning, regardless of the argument type. In particular, if
            the shift count is greater or equal to the number of bits in
            the bit argument, all bits in the result are 0.
          </p><p>
            For more information, see the introductory discussion in
            this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 4 &gt;&gt; 2;</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT HEX(_binary X'00FF00FF00FF' &gt;&gt; 8);</code></strong>
        -&gt; '0000FF00FF00'
</pre></li><li class="listitem"><a name="operator_bitwise-invert"></a><p>
            <a class="indexterm" name="idm46444325451552"></a>

            <a class="link" href="functions.html#operator_bitwise-invert"><code class="literal">~</code></a>
          </p><p>
            Invert all bits.
          </p><p>
            The result type depends on whether the bit argument is
            evaluated as a binary string or number:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the bit argument
                has a binary string type, and is not a hexadecimal
                literal, bit literal, or <code class="literal">NULL</code>
                literal. Numeric evaluation occurs otherwise, with
                argument conversion to an unsigned 64-bit integer as
                necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the bit argument. Numeric evaluation
                produces an unsigned 64-bit integer.
</p></li></ul>
</div>
<p>
            For more information, see the introductory discussion in
            this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 5 &amp; ~1;</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT HEX(~X'0000FFFF1111EEEE');</code></strong>
        -&gt; 'FFFF0000EEEE1111'
</pre></li><li class="listitem"><a name="function_bit-count"></a><p>
            <a class="indexterm" name="idm46444325437520"></a>

            <a class="link" href="functions.html#function_bit-count"><code class="literal">BIT_COUNT(<em class="replaceable"><code>N</code></em>)</code></a>
          </p><p>
            Returns the number of bits that are set in the argument
            <em class="replaceable"><code>N</code></em> as an unsigned 64-bit integer,
            or <code class="literal">NULL</code> if the argument is
            <code class="literal">NULL</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT BIT_COUNT(64), BIT_COUNT(BINARY 64);</code></strong>
        -&gt; 1, 7
mysql&gt; <strong class="userinput"><code>SELECT BIT_COUNT('64'), BIT_COUNT(_binary '64');</code></strong>
        -&gt; 1, 7
mysql&gt; <strong class="userinput"><code>SELECT BIT_COUNT(X'40'), BIT_COUNT(_binary X'40');</code></strong>
        -&gt; 1, 1
</pre></li></ul>
</div>

</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="encryption-functions"></a>12.13 Encryption and Compression Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444325425280"></a><a class="indexterm" name="idm46444325424240"></a>
<div class="table">
<a name="idm46444325422752"></a><p class="title"><b>Table 12.17 Encryption Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists encryption functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a></td>
<td>
      Decrypt using AES
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a></td>
<td>
      Encrypt using AES
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-decrypt"><code class="literal">ASYMMETRIC_DECRYPT()</code></a></td>
<td>
      Decrypt ciphertext using private or public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-derive"><code class="literal">ASYMMETRIC_DERIVE()</code></a></td>
<td>
      Derive symmetric key from asymmetric keys
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a></td>
<td>
      Encrypt cleartext using private or public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-sign"><code class="literal">ASYMMETRIC_SIGN()</code></a></td>
<td>
      Generate signature from digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-verify"><code class="literal">ASYMMETRIC_VERIFY()</code></a></td>
<td>
      Verify that signature matches digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_compress"><code class="literal">COMPRESS()</code></a></td>
<td>
      Return result as a binary string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a></td>
<td>
      Create private key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-asymmetric-pub-key"><code class="literal">CREATE_ASYMMETRIC_PUB_KEY()</code></a></td>
<td>
      Create public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a></td>
<td>
      Generate shared DH secret
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-digest"><code class="literal">CREATE_DIGEST()</code></a></td>
<td>
      Generate digest from string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a></td>
<td>
      Calculate MD5 checksum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_random-bytes"><code class="literal">RANDOM_BYTES()</code></a></td>
<td>
      Return a random byte vector
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code>, <code class="literal">SHA()</code></a></td>
<td>
      Calculate an SHA-1 160-bit checksum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sha2"><code class="literal">SHA2()</code></a></td>
<td>
      Calculate an SHA-2 checksum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_statement-digest"><code class="literal">STATEMENT_DIGEST()</code></a></td>
<td>
      Compute statement digest hash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_statement-digest-text"><code class="literal">STATEMENT_DIGEST_TEXT()</code></a></td>
<td>
      Compute normalized statement digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uncompress"><code class="literal">UNCOMPRESS()</code></a></td>
<td>
      Uncompress a string compressed
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uncompressed-length"><code class="literal">UNCOMPRESSED_LENGTH()</code></a></td>
<td>
      Return the length of a string before compression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_validate-password-strength"><code class="literal">VALIDATE_PASSWORD_STRENGTH()</code></a></td>
<td>
      Determine strength of password
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      Many encryption and compression functions return strings for which
      the result might contain arbitrary byte values. If you want to
      store these results, use a column with a
      <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a> or
      <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> binary string data type. This
      will avoid potential problems with trailing space removal or
      character set conversion that would change data values, such as
      may occur if you use a nonbinary string data type
      (<a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a>,
      <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>,
      <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">TEXT</code></a>).
    </p><p>
      Some encryption functions return strings of ASCII characters:
      <a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a>,
      <a class="link" href="functions.html#function_sha1"><code class="literal">SHA()</code></a>,
      <a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code></a>,
      <a class="link" href="functions.html#function_sha2"><code class="literal">SHA2()</code></a>,
      <a class="link" href="functions.html#function_statement-digest"><code class="literal">STATEMENT_DIGEST()</code></a>,
      <a class="link" href="functions.html#function_statement-digest-text"><code class="literal">STATEMENT_DIGEST_TEXT()</code></a>. Their
      return value is a string that has a character set and collation
      determined by the
      <a class="link" href="server-administration.html#sysvar_character_set_connection"><code class="literal">character_set_connection</code></a> and
      <a class="link" href="server-administration.html#sysvar_collation_connection"><code class="literal">collation_connection</code></a> system
      variables. This is a nonbinary string unless the character set is
      <code class="literal">binary</code>.
    </p><p>
      If an application stores values from a function such as
      <a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a> or
      <a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code></a> that returns a string of hex
      digits, more efficient storage and comparisons can be obtained by
      converting the hex representation to binary using
      <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a> and storing the result in a
      <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY(<em class="replaceable"><code>N</code></em>)</code></a>
      column. Each pair of hexadecimal digits requires one byte in
      binary form, so the value of <em class="replaceable"><code>N</code></em> depends
      on the length of the hex string. <em class="replaceable"><code>N</code></em> is
      16 for an <a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a> value and 20 for a
      <a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code></a> value. For
      <a class="link" href="functions.html#function_sha2"><code class="literal">SHA2()</code></a>,
      <em class="replaceable"><code>N</code></em> ranges from 28 to 32 depending on the
      argument specifying the desired bit length of the result.
    </p><p>
      The size penalty for storing the hex string in a
      <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a> column is at least two times,
      up to eight times if the value is stored in a column that uses the
      <code class="literal">utf8</code> character set (where each character uses 4
      bytes). Storing the string also results in slower comparisons
      because of the larger values and the need to take character set
      collation rules into account.
    </p><p>
      Suppose that an application stores
      <a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a> string values in a
      <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR(32)</code></a> column:
    </p><pre data-lang="sql" class="programlisting">CREATE TABLE md5_tbl (md5_val CHAR(32), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(MD5('abcdef'), ...);</pre><p>
      To convert hex strings to more compact form, modify the
      application to use <a class="link" href="functions.html#function_unhex"><code class="literal">UNHEX()</code></a> and
      <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY(16)</code></a> instead as follows:
    </p><pre data-lang="sql" class="programlisting">CREATE TABLE md5_tbl (md5_val BINARY(16), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(UNHEX(MD5('abcdef')), ...);</pre><p>
      Applications should be prepared to handle the very rare case that
      a hashing function produces the same value for two different input
      values. One way to make collisions detectable is to make the hash
      column a primary key.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
        Exploits for the MD5 and SHA-1 algorithms have become known. You
        may wish to consider using another one-way encryption function
        described in this section instead, such as
        <a class="link" href="functions.html#function_sha2"><code class="literal">SHA2()</code></a>.
</p>
</div>
<div class="caution" style="margin-left: 0.5in; margin-right: 0.5in;">
<div class="admon-title">
Caution
</div>
<p>
        Passwords or other sensitive values supplied as arguments to
        encryption functions are sent as cleartext to the MySQL server
        unless an SSL connection is used. Also, such values will appear
        in any MySQL logs to which they are written. To avoid these
        types of exposure, applications can encrypt sensitive values on
        the client side before sending them to the server. The same
        considerations apply to encryption keys. To avoid exposing
        these, applications can use stored procedures to encrypt and
        decrypt values on the server side.
</p>
</div>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_aes-decrypt"></a><p>
          <a class="indexterm" name="idm46444325299088"></a>

          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT(<em class="replaceable"><code>crypt_str</code></em>,<em class="replaceable"><code>key_str</code></em>[,<em class="replaceable"><code>init_vector</code></em>])</code></a>
        </p><p>
          This function decrypts data using the official AES (Advanced
          Encryption Standard) algorithm. For more information, see the
          description of <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a>.
        </p><p>
          Statements that use
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> are unsafe for
          statement-based replication.
        </p></li><li class="listitem"><a name="function_aes-encrypt"></a><p>
          <a class="indexterm" name="idm46444325287280"></a>

          <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>key_str</code></em>[,<em class="replaceable"><code>init_vector</code></em>])</code></a>
        </p><p>
          <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a> and
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> implement
          encryption and decryption of data using the official AES
          (Advanced Encryption Standard) algorithm, previously known as
          <span class="quote">“<span class="quote">Rijndael.</span>”</span> The AES standard permits various key
          lengths. By default these functions implement AES with a
          128-bit key length. Key lengths of 196 or 256 bits can be
          used, as described later. The key length is a trade off
          between performance and security.
        </p><p>
          <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a> encrypts the
          string <em class="replaceable"><code>str</code></em> using the key string
          <em class="replaceable"><code>key_str</code></em> and returns a binary string
          containing the encrypted output.
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> decrypts the
          encrypted string <em class="replaceable"><code>crypt_str</code></em> using
          the key string <em class="replaceable"><code>key_str</code></em> and returns
          the original plaintext string. If either function argument is
          <code class="literal">NULL</code>, the function returns
          <code class="literal">NULL</code>.
        </p><p>
          The <em class="replaceable"><code>str</code></em> and
          <em class="replaceable"><code>crypt_str</code></em> arguments can be any
          length, and padding is automatically added to
          <em class="replaceable"><code>str</code></em> so it is a multiple of a block
          as required by block-based algorithms such as AES. This
          padding is automatically removed by the
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> function. The
          length of <em class="replaceable"><code>crypt_str</code></em> can be
          calculated using this formula:
        </p><pre data-lang="clike" class="programlisting">16 * (trunc(<em class="replaceable"><code>string_length</code></em> / 16) + 1)
</pre><p>
          For a key length of 128 bits, the most secure way to pass a
          key to the <em class="replaceable"><code>key_str</code></em> argument is to
          create a truly random 128-bit value and pass it as a binary
          value. For example:
        </p><pre data-lang="sql" class="programlisting">INSERT INTO t
VALUES (1,AES_ENCRYPT('text',UNHEX('F3229A0B371ED2D9441B830D21A390C3')));</pre><p>
          A passphrase can be used to generate an AES key by hashing the
          passphrase. For example:
        </p><pre data-lang="sql" class="programlisting">INSERT INTO t
VALUES (1,AES_ENCRYPT('text', UNHEX(SHA2('My secret passphrase',512))));</pre><p>
          Do not pass a password or passphrase directly to
          <em class="replaceable"><code>crypt_str</code></em>, hash it first. Previous
          versions of this documentation suggested the former approach,
          but it is no longer recommended as the examples shown here are
          more secure.
        </p><p>
          If <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> detects
          invalid data or incorrect padding, it returns
          <code class="literal">NULL</code>. However, it is possible for
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> to return a
          non-<code class="literal">NULL</code> value (possibly garbage) if the
          input data or the key is invalid.
        </p><p>
          <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a> and
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> permit control of
          the block encryption mode and take an optional
          <em class="replaceable"><code>init_vector</code></em> initialization vector
          argument:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The <a class="link" href="server-administration.html#sysvar_block_encryption_mode"><code class="literal">block_encryption_mode</code></a>
              system variable controls the mode for block-based
              encryption algorithms. Its default value is
              <code class="literal">aes-128-ecb</code>, which signifies encryption
              using a key length of 128 bits and ECB mode. For a
              description of the permitted values of this variable, see
              <a class="xref" href="server-administration.html#server-system-variables" title="5.1.8 Server System Variables">Section 5.1.8, “Server System Variables”</a>.
            </p></li><li class="listitem"><p>
              The optional <em class="replaceable"><code>init_vector</code></em>
              argument provides an initialization vector for block
              encryption modes that require it.
</p></li></ul>
</div>
<p>
          For modes that require the optional
          <em class="replaceable"><code>init_vector</code></em> argument, it must be 16
          bytes or longer (bytes in excess of 16 are ignored). An error
          occurs if <em class="replaceable"><code>init_vector</code></em> is missing.
        </p><p>
          For modes that do not require
          <em class="replaceable"><code>init_vector</code></em>, it is ignored and a
          warning is generated if it is specified.
        </p><p>
          A random string of bytes to use for the initialization vector
          can be produced by calling
          <a class="link" href="functions.html#function_random-bytes"><code class="literal">RANDOM_BYTES(16)</code></a>. For
          encryption modes that require an initialization vector, the
          same vector must be used for encryption and decryption.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET block_encryption_mode = 'aes-256-cbc';</code></strong>
mysql&gt; <strong class="userinput"><code>SET @key_str = SHA2('My secret passphrase',512);</code></strong>
mysql&gt; <strong class="userinput"><code>SET @init_vector = RANDOM_BYTES(16);</code></strong>
mysql&gt; <strong class="userinput"><code>SET @crypt_str = AES_ENCRYPT('text',@key_str,@init_vector);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT AES_DECRYPT(@crypt_str,@key_str,@init_vector);</code></strong>
+-----------------------------------------------+
| AES_DECRYPT(@crypt_str,@key_str,@init_vector) |
+-----------------------------------------------+
| text                                          |
+-----------------------------------------------+
</pre><p>
          The following table lists each permitted block encryption mode
          and whether the initialization vector argument is required.
</p>
<div class="informaltable">
<table summary="The permitted encryption modes and whether the initialization vector argument is required for the mode."><col width="30%"><col width="35%"><thead><tr>
              <th scope="col">Block Encryption Mode</th>
              <th scope="col">Initialization Vector Required</th>
            </tr></thead><tbody><tr>
              <td scope="row">ECB</td>
              <td>No</td>
            </tr><tr>
              <td scope="row">CBC</td>
              <td>Yes</td>
            </tr><tr>
              <td scope="row">CFB1</td>
              <td>Yes</td>
            </tr><tr>
              <td scope="row">CFB8</td>
              <td>Yes</td>
            </tr><tr>
              <td scope="row">CFB128</td>
              <td>Yes</td>
            </tr><tr>
              <td scope="row">OFB</td>
              <td>Yes</td>
</tr></tbody></table>
</div>
<p>
          Statements that use
          <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a> or
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> are unsafe for
          statement-based replication.
        </p></li><li class="listitem"><a name="function_compress"></a><p>
          <a class="indexterm" name="idm46444325213424"></a>

          <a class="link" href="functions.html#function_compress"><code class="literal">COMPRESS(<em class="replaceable"><code>string_to_compress</code></em>)</code></a>
        </p><p>
          Compresses a string and returns the result as a binary string.
          This function requires MySQL to have been compiled with a
          compression library such as <code class="literal">zlib</code>.
          Otherwise, the return value is always <code class="literal">NULL</code>.
          The compressed string can be uncompressed with
          <a class="link" href="functions.html#function_uncompress"><code class="literal">UNCOMPRESS()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LENGTH(COMPRESS(REPEAT('a',1000)));</code></strong>
        -&gt; 21
mysql&gt; <strong class="userinput"><code>SELECT LENGTH(COMPRESS(''));</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT LENGTH(COMPRESS('a'));</code></strong>
        -&gt; 13
mysql&gt; <strong class="userinput"><code>SELECT LENGTH(COMPRESS(REPEAT('a',16)));</code></strong>
        -&gt; 15
</pre><p>
          The compressed string contents are stored the following way:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Empty strings are stored as empty strings.
            </p></li><li class="listitem"><p>
              Nonempty strings are stored as a 4-byte length of the
              uncompressed string (low byte first), followed by the
              compressed string. If the string ends with space, an extra
              <code class="literal">.</code> character is added to avoid problems
              with endspace trimming should the result be stored in a
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a> or
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a> column. (However,
              use of nonbinary string data types such as
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a> or
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a> to store compressed
              strings is not recommended anyway because character set
              conversion may occur. Use a
              <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a> or
              <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> binary string column
              instead.)
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_md5"></a><p>
          <a class="indexterm" name="idm46444325187744"></a>

          <a class="link" href="functions.html#function_md5"><code class="literal">MD5(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Calculates an MD5 128-bit checksum for the string. The value
          is returned as a string of 32 hexadecimal digits, or
          <code class="literal">NULL</code> if the argument was
          <code class="literal">NULL</code>. The return value can, for example, be
          used as a hash key. See the notes at the beginning of this
          section about storing hash values efficiently.
        </p><p>
          The return value is a string in the connection character set.
        </p><p>
          If FIPS mode is enabled,
          <code class="function">MD5()</code> returns
          <code class="literal">NULL</code>. See <a class="xref" href="security.html#fips-mode" title="6.5 FIPS Support">Section 6.5, “FIPS Support”</a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT MD5('testing');</code></strong>
        -&gt; 'ae2b1fca515949e5d54fb22b8ed95575'
</pre><p>
          This is the <span class="quote">“<span class="quote">RSA Data Security, Inc. MD5 Message-Digest
          Algorithm.</span>”</span>
        </p><p>
          See the note regarding the MD5 algorithm at the beginning this
          section.
        </p></li><li class="listitem"><a name="function_random-bytes"></a><p>
          <a class="indexterm" name="idm46444325171152"></a>

          <a class="link" href="functions.html#function_random-bytes"><code class="literal">RANDOM_BYTES(<em class="replaceable"><code>len</code></em>)</code></a>
        </p><p>
          This function returns a binary string of
          <em class="replaceable"><code>len</code></em> random bytes generated using
          the random number generator of the SSL library. Permitted
          values of <em class="replaceable"><code>len</code></em> range from 1 to 1024.
          For values outside that range, an error occurs.
        </p><p>
          <a class="link" href="functions.html#function_random-bytes"><code class="literal">RANDOM_BYTES()</code></a> can be used to
          provide the initialization vector for the
          <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a> and
          <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a> functions. For
          use in that context, <em class="replaceable"><code>len</code></em> must be at
          least 16. Larger values are permitted, but bytes in excess of
          16 are ignored.
        </p><p>
          <a class="link" href="functions.html#function_random-bytes"><code class="literal">RANDOM_BYTES()</code></a> generates a
          random value, which makes its result nondeterministic.
          Consequently, statements that use this function are unsafe for
          statement-based replication.
        </p></li><li class="listitem"><a name="function_sha1"></a><p>
          <a class="indexterm" name="idm46444325155728"></a>

          <a class="indexterm" name="idm46444325154656"></a>

          <a class="link" href="functions.html#function_sha1"><code class="literal">SHA1(<em class="replaceable"><code>str</code></em>)</code></a>,
          <a class="link" href="functions.html#function_sha1"><code class="literal">SHA(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Calculates an SHA-1 160-bit checksum for the string, as
          described in RFC 3174 (Secure Hash Algorithm). The value is
          returned as a string of 40 hexadecimal digits, or
          <code class="literal">NULL</code> if the argument was
          <code class="literal">NULL</code>. One of the possible uses for this
          function is as a hash key. See the notes at the beginning of
          this section about storing hash values efficiently.
          <a class="link" href="functions.html#function_sha1"><code class="literal">SHA()</code></a> is
          synonymous with <a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code></a>.
        </p><p>
          The return value is a string in the connection character set.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SHA1('abc');</code></strong>
        -&gt; 'a9993e364706816aba3e25717850c26c9cd0d89d'
</pre><p>
          <a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code></a> can be considered a
          cryptographically more secure equivalent of
          <a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a>. However, see the note
          regarding the MD5 and SHA-1 algorithms at the beginning this
          section.
        </p></li><li class="listitem"><a name="function_sha2"></a><p>
          <a class="indexterm" name="idm46444325135072"></a>

          <a class="link" href="functions.html#function_sha2"><code class="literal">SHA2(<em class="replaceable"><code>str</code></em>,
          <em class="replaceable"><code>hash_length</code></em>)</code></a>
        </p><p>
          Calculates the SHA-2 family of hash functions (SHA-224,
          SHA-256, SHA-384, and SHA-512). The first argument is the
          plaintext string to be hashed. The second argument indicates
          the desired bit length of the result, which must have a value
          of 224, 256, 384, 512, or 0 (which is equivalent to 256). If
          either argument is <code class="literal">NULL</code> or the hash length
          is not one of the permitted values, the return value is
          <code class="literal">NULL</code>. Otherwise, the function result is a
          hash value containing the desired number of bits. See the
          notes at the beginning of this section about storing hash
          values efficiently.
        </p><p>
          The return value is a string in the connection character set.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SHA2('abc', 224);</code></strong>
        -&gt; '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'
</pre><p>
          This function works only if MySQL has been configured with SSL
          support. See <a class="xref" href="security.html#encrypted-connections" title="6.3 Using Encrypted Connections">Section 6.3, “Using Encrypted Connections”</a>.
        </p><p>
          <a class="link" href="functions.html#function_sha2"><code class="literal">SHA2()</code></a> can be considered
          cryptographically more secure than
          <a class="link" href="functions.html#function_md5"><code class="literal">MD5()</code></a> or
          <a class="link" href="functions.html#function_sha1"><code class="literal">SHA1()</code></a>.
        </p></li><li class="listitem"><a name="function_statement-digest"></a><p>
          <a class="link" href="functions.html#function_statement-digest"><code class="literal">STATEMENT_DIGEST(<em class="replaceable"><code>statement</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444325114736"></a><p>
          Given an SQL statement as a string, returns the statement
          digest hash value as a string in the connection character set,
          or <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>. The related
          <a class="link" href="functions.html#function_statement-digest-text"><code class="literal">STATEMENT_DIGEST_TEXT()</code></a>
          function returns the normalized statement digest. For
          information about statement digesting, see
          <a class="xref" href="performance-schema.html#performance-schema-statement-digests" title="26.10 Performance Schema Statement Digests and Sampling">Section 26.10, “Performance Schema Statement Digests and Sampling”</a>.
        </p><p>
          Both functions use the MySQL parser to parse the statement. If
          parsing fails, an error occurs. The error message includes the
          parse error only if the statement is provided as a literal
          string.
        </p><p>
          The <a class="link" href="server-administration.html#sysvar_max_digest_length"><code class="literal">max_digest_length</code></a> system
          variable determines the maximum number of bytes available to
          these functions for computing normalized statement digests.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @stmt = 'SELECT * FROM mytable WHERE cola = 10 AND colb = 20';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT STATEMENT_DIGEST(@stmt);</code></strong>
+------------------------------------------------------------------+
| STATEMENT_DIGEST(@stmt)                                          |
+------------------------------------------------------------------+
| 3bb95eeade896657c4526e74ff2a2862039d0a0fe8a9e7155b5fe492cbd78387 |
+------------------------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT STATEMENT_DIGEST_TEXT(@stmt);</code></strong>
+----------------------------------------------------------+
| STATEMENT_DIGEST_TEXT(@stmt)                             |
+----------------------------------------------------------+
| SELECT * FROM `mytable` WHERE `cola` = ? AND `colb` = ?  |
+----------------------------------------------------------+
</pre></li><li class="listitem"><a name="function_statement-digest-text"></a><p>
          <a class="link" href="functions.html#function_statement-digest-text"><code class="literal">STATEMENT_DIGEST_TEXT(<em class="replaceable"><code>statement</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444325096432"></a><p>
          Given an SQL statement as a string, returns the normalized
          statement digest as a string in the connection character set,
          or <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>. For additional discussion and
          examples, see the description of the related
          <a class="link" href="functions.html#function_statement-digest"><code class="literal">STATEMENT_DIGEST()</code></a> function.
        </p></li><li class="listitem"><a name="function_uncompress"></a><p>
          <a class="indexterm" name="idm46444325089072"></a>

          <a class="link" href="functions.html#function_uncompress"><code class="literal">UNCOMPRESS(<em class="replaceable"><code>string_to_uncompress</code></em>)</code></a>
        </p><p>
          Uncompresses a string compressed by the
          <a class="link" href="functions.html#function_compress"><code class="literal">COMPRESS()</code></a> function. If the
          argument is not a compressed value, the result is
          <code class="literal">NULL</code>. This function requires MySQL to have
          been compiled with a compression library such as
          <code class="literal">zlib</code>. Otherwise, the return value is always
          <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UNCOMPRESS(COMPRESS('any string'));</code></strong>
        -&gt; 'any string'
mysql&gt; <strong class="userinput"><code>SELECT UNCOMPRESS('any string');</code></strong>
        -&gt; NULL
</pre></li><li class="listitem"><a name="function_uncompressed-length"></a><p>
          <a class="indexterm" name="idm46444325075168"></a>

          <a class="link" href="functions.html#function_uncompressed-length"><code class="literal">UNCOMPRESSED_LENGTH(<em class="replaceable"><code>compressed_string</code></em>)</code></a>
        </p><p>
          Returns the length that the compressed string had before being
          compressed.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30)));</code></strong>
        -&gt; 30
</pre></li><li class="listitem"><a name="function_validate-password-strength"></a><p>
          <a class="indexterm" name="idm46444325065616"></a>

          <a class="link" href="functions.html#function_validate-password-strength"><code class="literal">VALIDATE_PASSWORD_STRENGTH(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Given an argument representing a plaintext password, this
          function returns an integer to indicate how strong the
          password is. The return value ranges from 0 (weak) to 100
          (strong).
        </p><p>
          Password assessment by
          <a class="link" href="functions.html#function_validate-password-strength"><code class="literal">VALIDATE_PASSWORD_STRENGTH()</code></a> is
          done by the <code class="literal">validate_password</code> component. If
          that component is not installed, the function always returns
          0. For information about installing
          <code class="literal">validate_password</code>, see
          <a class="xref" href="security.html#validate-password" title="6.4.3 The Password Validation Component">Section 6.4.3, “The Password Validation Component”</a>. To examine or configure
          the parameters that affect password testing, check or set the
          system variables implemented by
          <code class="literal">validate_password</code>. See
          <a class="xref" href="security.html#validate-password-options-variables" title="6.4.3.2 Password Validation Options and Variables">Section 6.4.3.2, “Password Validation Options and Variables”</a>.
        </p><p>
          The password is subjected to increasingly strict tests and the
          return value reflects which tests were satisfied, as shown in
          the following table. In addition, if the
          <a class="link" href="security.html#sysvar_validate_password.check_user_name"><code class="literal">validate_password.check_user_name</code></a>
          system variable is enabled and the password matches the user
          name,
          <a class="link" href="functions.html#function_validate-password-strength"><code class="literal">VALIDATE_PASSWORD_STRENGTH()</code></a>
          returns 0 regardless of how other
          <code class="literal">validate_password</code> system variables are set.
</p>
<div class="informaltable">
<table summary="Password tests of the VALIDATE_PASSWORD_STRENGTH() function and the values returned by each password test."><col width="60%"><col width="20%"><thead><tr>
              <th scope="col">Password Test</th>
              <th scope="col">Return Value</th>
            </tr></thead><tbody><tr>
              <td scope="row">Length &lt; 4</td>
              <td>0</td>
            </tr><tr>
              <td scope="row">Length ≥ 4 and &lt;
                <a class="link" href="security.html#sysvar_validate_password.length"><code class="literal">validate_password.length</code></a></td>
              <td>25</td>
            </tr><tr>
              <td scope="row">Satisfies policy 1 (<code class="literal">LOW</code>)</td>
              <td>50</td>
            </tr><tr>
              <td scope="row">Satisfies policy 2 (<code class="literal">MEDIUM</code>)</td>
              <td>75</td>
            </tr><tr>
              <td scope="row">Satisfies policy 3 (<code class="literal">STRONG</code>)</td>
              <td>100</td>
</tr></tbody></table>
</div>
</li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="locking-functions"></a>12.14 Locking Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444325028672"></a><a class="indexterm" name="idm46444325027600"></a><p>
      This section describes functions used to manipulate user-level
      locks.
</p>
<div class="table">
<a name="idm46444325025632"></a><p class="title"><b>Table 12.18 Locking Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists locking functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a></td>
<td>
      Get a named lock
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-free-lock"><code class="literal">IS_FREE_LOCK()</code></a></td>
<td>
      Whether the named lock is free
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-used-lock"><code class="literal">IS_USED_LOCK()</code></a></td>
<td>
      Whether the named lock is in use; return connection identifier if
      true
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_release-all-locks"><code class="literal">RELEASE_ALL_LOCKS()</code></a></td>
<td>
      Release all current named locks
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_release-lock"><code class="literal">RELEASE_LOCK()</code></a></td>
<td>
      Release the named lock
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_get-lock"></a><p>
          <a class="indexterm" name="idm46444324999728"></a>

          <a class="indexterm" name="idm46444324998656"></a>

          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK(<em class="replaceable"><code>str</code></em>,<em class="replaceable"><code>timeout</code></em>)</code></a>
        </p><p>
          Tries to obtain a lock with a name given by the string
          <em class="replaceable"><code>str</code></em>, using a timeout of
          <em class="replaceable"><code>timeout</code></em> seconds. A negative
          <em class="replaceable"><code>timeout</code></em> value means infinite
          timeout. The lock is exclusive. While held by one session,
          other sessions cannot obtain a lock of the same name.
        </p><p>
          Returns <code class="literal">1</code> if the lock was obtained
          successfully, <code class="literal">0</code> if the attempt timed out
          (for example, because another client has previously locked the
          name), or <code class="literal">NULL</code> if an error occurred (such
          as running out of memory or the thread was killed with
          <a class="link" href="programs.html#mysqladmin" title="4.5.2 mysqladmin — Client for Administering a MySQL Server"><span class="command"><strong>mysqladmin kill</strong></span></a>).
        </p><p>
          A lock obtained with <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a>
          is released explicitly by executing
          <a class="link" href="functions.html#function_release-lock"><code class="literal">RELEASE_LOCK()</code></a> or implicitly
          when your session terminates (either normally or abnormally).
          Locks obtained with <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a>
          are not released when transactions commit or roll back.
        </p><p>
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> is implemented using
          the metadata locking (MDL) subsystem. Multiple simultaneous
          locks can be acquired and
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> does not release any
          existing locks. For example, suppose that you execute these
          statements:
        </p><pre data-lang="sql" class="programlisting">SELECT GET_LOCK('lock1',10);
SELECT GET_LOCK('lock2',10);
SELECT RELEASE_LOCK('lock2');
SELECT RELEASE_LOCK('lock1');</pre><p>
          The second <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> acquires
          a second lock and both
          <a class="link" href="functions.html#function_release-lock"><code class="literal">RELEASE_LOCK()</code></a> calls return 1
          (success).
        </p><p>
          It is even possible for a given session to acquire multiple
          locks for the same name. Other sessions cannot acquire a lock
          with that name until the acquiring session releases all its
          locks for the name.
        </p><p>
          Uniquely named locks acquired with
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> appear in the
          Performance Schema <a class="link" href="performance-schema.html#metadata-locks-table" title="26.12.13.3 The metadata_locks Table"><code class="literal">metadata_locks</code></a>
          table. The <code class="literal">OBJECT_TYPE</code> column says
          <code class="literal">USER LEVEL LOCK</code> and the
          <code class="literal">OBJECT_NAME</code> column indicates the lock name.
          In the case that multiple locks are acquired for the
          <span class="emphasis"><em>same</em></span> name, only the first lock for the
          name registers a row in the
          <a class="link" href="performance-schema.html#metadata-locks-table" title="26.12.13.3 The metadata_locks Table"><code class="literal">metadata_locks</code></a> table. Subsequent
          locks for the name increment a counter in the lock but do not
          acquire additional metadata locks. The
          <a class="link" href="performance-schema.html#metadata-locks-table" title="26.12.13.3 The metadata_locks Table"><code class="literal">metadata_locks</code></a> row for the lock
          is deleted when the last lock instance on the name is
          released.
        </p><p>
          The capability of acquiring multiple locks means there is the
          possibility of deadlock among clients. When this happens, the
          server chooses a caller and terminates its lock-acquisition
          request with an
          <a class="link" href="error-handling.html#error_er_user_lock_deadlock"><code class="literal">ER_USER_LOCK_DEADLOCK</code></a> error.
          This error does not cause transactions to roll back.
        </p><p>
          MySQL enforces a maximum length on lock names of 64
          characters.
        </p><p>
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> can be used to
          implement application locks or to simulate record locks. Names
          are locked on a server-wide basis. If a name has been locked
          within one session, <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a>
          blocks any request by another session for a lock with the same
          name. This enables clients that agree on a given lock name to
          use the name to perform cooperative advisory locking. But be
          aware that it also enables a client that is not among the set
          of cooperating clients to lock a name, either inadvertently or
          deliberately, and thus prevent any of the cooperating clients
          from locking that name. One way to reduce the likelihood of
          this is to use lock names that are database-specific or
          application-specific. For example, use lock names of the form
          <em class="replaceable"><code>db_name.str</code></em> or
          <em class="replaceable"><code>app_name.str</code></em>.
        </p><p>
          If multiple clients are waiting for a lock, the order in which
          they will acquire it is undefined. Applications should not
          assume that clients will acquire the lock in the same order
          that they issued the lock requests.
        </p><p>
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> is unsafe for
          statement-based replication. A warning is logged if you use
          this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
</p>
<div class="caution" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Caution
</div>
<p>
            With the capability of acquiring multiple named locks, it is
            possible for a single statement to acquire a large number of
            locks. For example:
          </p><pre data-lang="sql" class="programlisting">INSERT INTO ... SELECT GET_LOCK(t1.col_name) FROM t1;</pre><p>
            These types of statements may have certain adverse effects.
            For example, if the statement fails part way through and
            rolls back, locks acquired up to the point of failure will
            still exist. If the intent is for there to be a
            correspondence between rows inserted and locks acquired,
            that intent will not be satisfied. Also, if it is important
            that locks are granted in a certain order, be aware that
            result set order may differ depending on which execution
            plan the optimizer chooses. For these reasons, it may be
            best to limit applications to a single lock-acquisition call
            per statement.
</p>
</div>
<p>
          A different locking interface is available as either a plugin
          service or a set of user-defined functions. This interface
          provides lock namespaces and distinct read and write locks,
          unlike the interface provided by
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> and related
          functions. For details, see <a class="xref" href="extending-mysql.html#locking-service" title="29.3.1 The Locking Service">Section 29.3.1, “The Locking Service”</a>.
        </p></li><li class="listitem"><a name="function_is-free-lock"></a><p>
          <a class="indexterm" name="idm46444324947888"></a>

          <a class="link" href="functions.html#function_is-free-lock"><code class="literal">IS_FREE_LOCK(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Checks whether the lock named <em class="replaceable"><code>str</code></em>
          is free to use (that is, not locked). Returns
          <code class="literal">1</code> if the lock is free (no one is using the
          lock), <code class="literal">0</code> if the lock is in use, and
          <code class="literal">NULL</code> if an error occurs (such as an
          incorrect argument).
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p></li><li class="listitem"><a name="function_is-used-lock"></a><p>
          <a class="indexterm" name="idm46444324935568"></a>

          <a class="link" href="functions.html#function_is-used-lock"><code class="literal">IS_USED_LOCK(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Checks whether the lock named <em class="replaceable"><code>str</code></em>
          is in use (that is, locked). If so, it returns the connection
          identifier of the client session that holds the lock.
          Otherwise, it returns <code class="literal">NULL</code>.
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p></li><li class="listitem"><a name="function_release-all-locks"></a><p>
          <a class="indexterm" name="idm46444324924480"></a>

          <a class="link" href="functions.html#function_release-all-locks"><code class="literal">RELEASE_ALL_LOCKS()</code></a>
        </p><p>
          Releases all named locks held by the current session and
          returns the number of locks released (0 if there were none)
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p></li><li class="listitem"><a name="function_release-lock"></a><p>
          <a class="indexterm" name="idm46444324915072"></a>

          <a class="link" href="functions.html#function_release-lock"><code class="literal">RELEASE_LOCK(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Releases the lock named by the string
          <em class="replaceable"><code>str</code></em> that was obtained with
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a>. Returns
          <code class="literal">1</code> if the lock was released,
          <code class="literal">0</code> if the lock was not established by this
          thread (in which case the lock is not released), and
          <code class="literal">NULL</code> if the named lock did not exist. The
          lock does not exist if it was never obtained by a call to
          <a class="link" href="functions.html#function_get-lock"><code class="literal">GET_LOCK()</code></a> or if it has
          previously been released.
        </p><p>
          The <a class="link" href="sql-statements.html#do" title="13.2.3 DO Statement"><code class="literal">DO</code></a> statement is convenient
          to use with <a class="link" href="functions.html#function_release-lock"><code class="literal">RELEASE_LOCK()</code></a>. See
          <a class="xref" href="sql-statements.html#do" title="13.2.3 DO Statement">Section 13.2.3, “DO Statement”</a>.
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
</p></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="information-functions"></a>12.15 Information Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444324897520"></a><a class="indexterm" name="idm46444324896448"></a>
<div class="table">
<a name="idm46444324894960"></a><p class="title"><b>Table 12.19 Information Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists information functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK()</code></a></td>
<td>
      Repeatedly execute an expression
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_charset"><code class="literal">CHARSET()</code></a></td>
<td>
      Return the character set of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_coercibility"><code class="literal">COERCIBILITY()</code></a></td>
<td>
      Return the collation coercibility value of the string argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_collation"><code class="literal">COLLATION()</code></a></td>
<td>
      Return the collation of the string argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_connection-id"><code class="literal">CONNECTION_ID()</code></a></td>
<td>
      Return the connection ID (thread ID) for the connection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-role"><code class="literal">CURRENT_ROLE()</code></a></td>
<td>
      Return the current active roles
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code>, <code class="literal">CURRENT_USER</code></a></td>
<td>
      The authenticated user name and host name
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_database"><code class="literal">DATABASE()</code></a></td>
<td>
      Return the default (current) database name
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a></td>
<td>
      For a SELECT with a LIMIT clause, the number of rows that would be
      returned were there no LIMIT clause
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_icu-version"><code class="literal">ICU_VERSION()</code></a></td>
<td>
      ICU library version
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a></td>
<td>
      Value of the AUTOINCREMENT column for the last INSERT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_roles-graphml"><code class="literal">ROLES_GRAPHML()</code></a></td>
<td>
      Return a GraphML document representing memory role subgraphs
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_row-count"><code class="literal">ROW_COUNT()</code></a></td>
<td>
      The number of rows updated
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_schema"><code class="literal">SCHEMA()</code></a></td>
<td>
      Synonym for DATABASE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_session-user"><code class="literal">SESSION_USER()</code></a></td>
<td>
      Synonym for USER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_system-user"><code class="literal">SYSTEM_USER()</code></a></td>
<td>
      Synonym for USER()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a></td>
<td>
      The user name and host name provided by the client
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_version"><code class="literal">VERSION()</code></a></td>
<td>
      Return a string that indicates the MySQL server version
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_benchmark"></a><p>
          <a class="indexterm" name="idm46444324826272"></a>

          <a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK(<em class="replaceable"><code>count</code></em>,<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          The <a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK()</code></a> function
          executes the expression <em class="replaceable"><code>expr</code></em>
          repeatedly <em class="replaceable"><code>count</code></em> times. It may be
          used to time how quickly MySQL processes the expression. The
          result value is <code class="literal">0</code>, or
          <code class="literal">NULL</code> for inappropriate arguments such as a
          <code class="literal">NULL</code> or negative repeat count.
        </p><p>
          The intended use is from within the <a class="link" href="programs.html#mysql" title="4.5.1 mysql — The MySQL Command-Line Client"><span class="command"><strong>mysql</strong></span></a>
          client, which reports query execution times:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT BENCHMARK(1000000,AES_ENCRYPT('hello','goodbye'));</code></strong>
+---------------------------------------------------+
| BENCHMARK(1000000,AES_ENCRYPT('hello','goodbye')) |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
1 row in set (4.74 sec)
</pre><p>
          The time reported is elapsed time on the client end, not CPU
          time on the server end. It is advisable to execute
          <a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK()</code></a> several times, and
          to interpret the result with regard to how heavily loaded the
          server machine is.
        </p><p>
          <a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK()</code></a> is intended for
          measuring the runtime performance of scalar expressions, which
          has some significant implications for the way that you use it
          and interpret the results:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Only scalar expressions can be used. Although the
              expression can be a subquery, it must return a single
              column and at most a single row. For example,
              <a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK(10, (SELECT * FROM
              t))</code></a> will fail if the table <code class="literal">t</code>
              has more than one column or more than one row.
            </p></li><li class="listitem"><p>
              Executing a <code class="literal">SELECT
              <em class="replaceable"><code>expr</code></em></code> statement
              <em class="replaceable"><code>N</code></em> times differs from executing
              <code class="literal">SELECT BENCHMARK(<em class="replaceable"><code>N</code></em>,
              <em class="replaceable"><code>expr</code></em>)</code> in terms of the
              amount of overhead involved. The two have very different
              execution profiles and you should not expect them to take
              the same amount of time. The former involves the parser,
              optimizer, table locking, and runtime evaluation
              <em class="replaceable"><code>N</code></em> times each. The latter
              involves only runtime evaluation
              <em class="replaceable"><code>N</code></em> times, and all the other
              components just once. Memory structures already allocated
              are reused, and runtime optimizations such as local
              caching of results already evaluated for aggregate
              functions can alter the results. Use of
              <a class="link" href="functions.html#function_benchmark"><code class="literal">BENCHMARK()</code></a> thus measures
              performance of the runtime component by giving more weight
              to that component and removing the <span class="quote">“<span class="quote">noise</span>”</span>
              introduced by the network, parser, optimizer, and so
              forth.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_charset"></a><p>
          <a class="indexterm" name="idm46444324795680"></a>

          <a class="link" href="functions.html#function_charset"><code class="literal">CHARSET(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the character set of the string argument.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CHARSET('abc');</code></strong>
        -&gt; 'utf8'
mysql&gt; <strong class="userinput"><code>SELECT CHARSET(CONVERT('abc' USING latin1));</code></strong>
        -&gt; 'latin1'
mysql&gt; <strong class="userinput"><code>SELECT CHARSET(USER());</code></strong>
        -&gt; 'utf8'
</pre></li><li class="listitem"><a name="function_coercibility"></a><p>
          <a class="indexterm" name="idm46444324784672"></a>

          <a class="link" href="functions.html#function_coercibility"><code class="literal">COERCIBILITY(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the collation coercibility value of the string
          argument.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COERCIBILITY('abc' COLLATE utf8_swedish_ci);</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT COERCIBILITY(USER());</code></strong>
        -&gt; 3
mysql&gt; <strong class="userinput"><code>SELECT COERCIBILITY('abc');</code></strong>
        -&gt; 4
mysql&gt; <strong class="userinput"><code>SELECT COERCIBILITY(1000);</code></strong>
        -&gt; 5
</pre><p>
          The return values have the meanings shown in the following
          table. Lower values have higher precedence.
</p>
<div class="informaltable">
<table summary="Collation coercibility return values, the meaning of each value, and an example of each."><col width="15%"><col width="15%"><col width="70%"><thead><tr>
              <th scope="col">Coercibility</th>
              <th scope="col">Meaning</th>
              <th scope="col">Example</th>
            </tr></thead><tbody><tr>
              <td scope="row"><code class="literal">0</code></td>
              <td>Explicit collation</td>
              <td>Value with <code class="literal">COLLATE</code> clause</td>
            </tr><tr>
              <td scope="row"><code class="literal">1</code></td>
              <td>No collation</td>
              <td>Concatenation of strings with different collations</td>
            </tr><tr>
              <td scope="row"><code class="literal">2</code></td>
              <td>Implicit collation</td>
              <td>Column value, stored routine parameter or local variable</td>
            </tr><tr>
              <td scope="row"><code class="literal">3</code></td>
              <td>System constant</td>
              <td><a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a> return value</td>
            </tr><tr>
              <td scope="row"><code class="literal">4</code></td>
              <td>Coercible</td>
              <td>Literal string</td>
            </tr><tr>
              <td scope="row"><code class="literal">5</code></td>
              <td>Numeric</td>
              <td>Numeric or temporal value</td>
            </tr><tr>
              <td scope="row"><code class="literal">5</code></td>
              <td>Ignorable</td>
              <td><code class="literal">NULL</code> or an expression derived from
                <code class="literal">NULL</code></td>
</tr></tbody></table>
</div>
<p>
          For more information, see
          <a class="xref" href="charset.html#charset-collation-coercibility" title="10.8.4 Collation Coercibility in Expressions">Section 10.8.4, “Collation Coercibility in Expressions”</a>.
        </p></li><li class="listitem"><a name="function_collation"></a><p>
          <a class="indexterm" name="idm46444324734960"></a>

          <a class="link" href="functions.html#function_collation"><code class="literal">COLLATION(<em class="replaceable"><code>str</code></em>)</code></a>
        </p><p>
          Returns the collation of the string argument.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COLLATION('abc');</code></strong>
        -&gt; 'utf8_general_ci'
mysql&gt; <strong class="userinput"><code>SELECT COLLATION(_utf8mb4'abc');</code></strong>
        -&gt; 'utf8mb4_0900_ai_ci'
mysql&gt; <strong class="userinput"><code>SELECT COLLATION(_latin1'abc');</code></strong>
        -&gt; 'latin1_swedish_ci'
</pre></li><li class="listitem"><a name="function_connection-id"></a><p>
          <a class="indexterm" name="idm46444324723936"></a>

          <a class="link" href="functions.html#function_connection-id"><code class="literal">CONNECTION_ID()</code></a>
        </p><p>
          Returns the connection ID (thread ID) for the connection.
          Every connection has an ID that is unique among the set of
          currently connected clients.
        </p><p>
          The value returned by
          <a class="link" href="functions.html#function_connection-id"><code class="literal">CONNECTION_ID()</code></a> is the same
          type of value as displayed in the <code class="literal">ID</code> column
          of the
          <a class="link" href="information-schema.html#processlist-table" title="25.22 The INFORMATION_SCHEMA PROCESSLIST Table"><code class="literal">INFORMATION_SCHEMA.PROCESSLIST</code></a>
          table, the <code class="literal">Id</code> column of
          <a class="link" href="sql-statements.html#show-processlist" title="13.7.7.29 SHOW PROCESSLIST Statement"><code class="literal">SHOW PROCESSLIST</code></a> output, and
          the <code class="literal">PROCESSLIST_ID</code> column of the
          Performance Schema <a class="link" href="performance-schema.html#threads-table" title="26.12.19.5 The threads Table"><code class="literal">threads</code></a> table.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CONNECTION_ID();</code></strong>
        -&gt; 23786
</pre></li><li class="listitem"><a name="function_current-role"></a><p>
          <a class="indexterm" name="idm46444324706480"></a>

          <a class="link" href="functions.html#function_current-role"><code class="literal">CURRENT_ROLE()</code></a>
        </p><p>
          Returns a <code class="literal">utf8</code> string containing the
          current active roles for the current session, separated by
          commas, or <code class="literal">NONE</code> if there are none. The
          value reflects the setting of the
          <a class="link" href="server-administration.html#sysvar_sql_quote_show_create"><code class="literal">sql_quote_show_create</code></a> system
          variable.
        </p><p>
          Suppose that an account is granted roles as follows:
        </p><pre data-lang="sql" class="programlisting">GRANT 'r1', 'r2' TO 'u1'@'localhost';
SET DEFAULT ROLE ALL TO 'u1'@'localhost';</pre><p>
          In sessions for <code class="literal">u1</code>, the initial
          <a class="link" href="functions.html#function_current-role"><code class="literal">CURRENT_ROLE()</code></a> value names the
          default account roles. Using <a class="link" href="sql-statements.html#set-role" title="13.7.1.11 SET ROLE Statement"><code class="literal">SET
          ROLE</code></a> changes that:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CURRENT_ROLE();</code></strong>
+-------------------+
| CURRENT_ROLE()    |
+-------------------+
| `r1`@`%`,`r2`@`%` |
+-------------------+
mysql&gt; <strong class="userinput"><code>SET ROLE 'r1'; SELECT CURRENT_ROLE();</code></strong>
+----------------+
| CURRENT_ROLE() |
+----------------+
| `r1`@`%`       |
+----------------+
</pre></li><li class="listitem"><a name="function_current-user"></a><p>
          <a class="indexterm" name="idm46444324689056"></a>

          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER</code></a>,
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a>
        </p><p>
          Returns the user name and host name combination for the MySQL
          account that the server used to authenticate the current
          client. This account determines your access privileges. The
          return value is a string in the <code class="literal">utf8</code>
          character set.
        </p><p>
          The value of <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a> can
          differ from the value of
          <a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT USER();</code></strong>
        -&gt; 'davida@localhost'
mysql&gt; <strong class="userinput"><code>SELECT * FROM mysql.user;</code></strong>
ERROR 1044: Access denied for user ''@'localhost' to
database 'mysql'
mysql&gt; <strong class="userinput"><code>SELECT CURRENT_USER();</code></strong>
        -&gt; '@localhost'
</pre><p>
          The example illustrates that although the client specified a
          user name of <code class="literal">davida</code> (as indicated by the
          value of the <a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a> function),
          the server authenticated the client using an anonymous user
          account (as seen by the empty user name part of the
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a> value). One way
          this might occur is that there is no account listed in the
          grant tables for <code class="literal">davida</code>.
        </p><p>
          Within a stored program or view,
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a> returns the
          account for the user who defined the object (as given by its
          <code class="literal">DEFINER</code> value) unless defined with the
          <code class="literal">SQL SECURITY INVOKER</code> characteristic. In the
          latter case, <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a>
          returns the object's invoker.
        </p><p>
          Triggers and events have no option to define the <code class="literal">SQL
          SECURITY</code> characteristic, so for these objects,
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a> returns the
          account for the user who defined the object. To return the
          invoker, use <a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a> or
          <a class="link" href="functions.html#function_session-user"><code class="literal">SESSION_USER()</code></a>.
        </p><p>
          The following statements support use of the
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a> function to take
          the place of the name of (and, possibly, a host for) an
          affected user or a definer; in such cases,
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a> is expanded
          where and as needed:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <a class="link" href="sql-statements.html#drop-user" title="13.7.1.5 DROP USER Statement"><code class="literal">DROP USER</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#rename-user" title="13.7.1.7 RENAME USER Statement"><code class="literal">RENAME USER</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#grant" title="13.7.1.6 GRANT Statement"><code class="literal">GRANT</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#revoke" title="13.7.1.8 REVOKE Statement"><code class="literal">REVOKE</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#create-function" title="13.1.14 CREATE FUNCTION Statement"><code class="literal">CREATE FUNCTION</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#create-procedure" title="13.1.17 CREATE PROCEDURE and CREATE FUNCTION Statements"><code class="literal">CREATE PROCEDURE</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#create-trigger" title="13.1.22 CREATE TRIGGER Statement"><code class="literal">CREATE TRIGGER</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#create-event" title="13.1.13 CREATE EVENT Statement"><code class="literal">CREATE EVENT</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#create-view" title="13.1.23 CREATE VIEW Statement"><code class="literal">CREATE VIEW</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#alter-event" title="13.1.3 ALTER EVENT Statement"><code class="literal">ALTER EVENT</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#alter-view" title="13.1.11 ALTER VIEW Statement"><code class="literal">ALTER VIEW</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#set-password" title="13.7.1.10 SET PASSWORD Statement"><code class="literal">SET PASSWORD</code></a>
</p></li></ul>
</div>
<p>
          For information about the implications that this expansion of
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a> has for
          replication, see
          <a class="xref" href="replication.html#replication-features-current-user" title="17.5.1.8 Replication of CURRENT_USER()">Section 17.5.1.8, “Replication of CURRENT_USER()”</a>.
        </p></li><li class="listitem"><a name="function_database"></a><p>
          <a class="indexterm" name="idm46444324628944"></a>

          <a class="link" href="functions.html#function_database"><code class="literal">DATABASE()</code></a>
        </p><p>
          Returns the default (current) database name as a string in the
          <code class="literal">utf8</code> character set. If there is no default
          database, <a class="link" href="functions.html#function_database"><code class="literal">DATABASE()</code></a> returns
          <code class="literal">NULL</code>. Within a stored routine, the default
          database is the database that the routine is associated with,
          which is not necessarily the same as the database that is the
          default in the calling context.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT DATABASE();</code></strong>
        -&gt; 'test'
</pre><p>
          If there is no default database,
          <a class="link" href="functions.html#function_database"><code class="literal">DATABASE()</code></a> returns
          <code class="literal">NULL</code>.
        </p></li><li class="listitem"><a name="function_found-rows"></a><p>
          <a class="indexterm" name="idm46444324614608"></a>

          <a class="indexterm" name="idm46444324613536"></a>

          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a>
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The <code class="literal">SQL_CALC_FOUND_ROWS</code> query modifier
            and accompanying <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a>
            function are deprecated as of MySQL 8.0.17 and will be
            removed in a future MySQL version. As a replacement,
            considering executing your query with
            <code class="literal">LIMIT</code>, and then a second query with
            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(*)</code></a> and without
            <code class="literal">LIMIT</code> to determine whether there are
            additional rows. For example, instead of these queries:
          </p><pre data-lang="sql" class="programlisting">SELECT SQL_CALC_FOUND_ROWS * FROM <em class="replaceable"><code>tbl_name</code></em> WHERE id &gt; 100 LIMIT 10;
SELECT FOUND_ROWS();
</pre><p>
            Use these queries instead:
          </p><pre data-lang="sql" class="programlisting">SELECT * FROM <em class="replaceable"><code>tbl_name</code></em> WHERE id &gt; 100 LIMIT 10;
SELECT COUNT(*) FROM <em class="replaceable"><code>tbl_name</code></em> WHERE id &gt; 100;
</pre><p>
            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(*)</code></a> is subject to
            certain optimizations.
            <code class="literal">SQL_CALC_FOUND_ROWS</code> causes some
            optimizations to be disabled.
</p>
</div>
<p>
          A <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement may include
          a <code class="literal">LIMIT</code> clause to restrict the number of
          rows the server returns to the client. In some cases, it is
          desirable to know how many rows the statement would have
          returned without the <code class="literal">LIMIT</code>, but without
          running the statement again. To obtain this row count, include
          an <code class="literal">SQL_CALC_FOUND_ROWS</code> option in the
          <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement, and then
          invoke <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> afterward:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SQL_CALC_FOUND_ROWS * FROM <em class="replaceable"><code>tbl_name</code></em></code></strong>
    -&gt; <strong class="userinput"><code>WHERE id &gt; 100 LIMIT 10;</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT FOUND_ROWS();</code></strong>
</pre><p>
          The second <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> returns a
          number indicating how many rows the first
          <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> would have returned had
          it been written without the <code class="literal">LIMIT</code> clause.
        </p><p>
          In the absence of the <code class="literal">SQL_CALC_FOUND_ROWS</code>
          option in the most recent successful
          <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement,
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> returns the number
          of rows in the result set returned by that statement. If the
          statement includes a <code class="literal">LIMIT</code> clause,
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> returns the number
          of rows up to the limit. For example,
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> returns 10 or 60,
          respectively, if the statement includes <code class="literal">LIMIT
          10</code> or <code class="literal">LIMIT 50, 10</code>.
        </p><p>
          The row count available through
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> is transient and
          not intended to be available past the statement following the
          <code class="literal">SELECT SQL_CALC_FOUND_ROWS</code> statement. If
          you need to refer to the value later, save it:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SQL_CALC_FOUND_ROWS * FROM ... ;</code></strong>
mysql&gt; <strong class="userinput"><code>SET @rows = FOUND_ROWS();</code></strong>
</pre><p>
          If you are using <code class="literal">SELECT
          SQL_CALC_FOUND_ROWS</code>, MySQL must calculate how many
          rows are in the full result set. However, this is faster than
          running the query again without <code class="literal">LIMIT</code>,
          because the result set need not be sent to the client.
        </p><p>
          <code class="literal">SQL_CALC_FOUND_ROWS</code> and
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> can be useful in
          situations when you want to restrict the number of rows that a
          query returns, but also determine the number of rows in the
          full result set without running the query again. An example is
          a Web script that presents a paged display containing links to
          the pages that show other sections of a search result. Using
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> enables you to
          determine how many other pages are needed for the rest of the
          result.
        </p><p>
          The use of <code class="literal">SQL_CALC_FOUND_ROWS</code> and
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> is more complex
          for <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a> statements than for
          simple <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statements,
          because <code class="literal">LIMIT</code> may occur at multiple places
          in a <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a>. It may be applied
          to individual <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statements
          in the <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a>, or global to the
          <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a> result as a whole.
        </p><p>
          The intent of <code class="literal">SQL_CALC_FOUND_ROWS</code> for
          <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a> is that it should return
          the row count that would be returned without a global
          <code class="literal">LIMIT</code>. The conditions for use of
          <code class="literal">SQL_CALC_FOUND_ROWS</code> with
          <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a> are:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The <code class="literal">SQL_CALC_FOUND_ROWS</code> keyword must
              appear in the first <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>
              of the <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a>.
            </p></li><li class="listitem"><p>
              The value of <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a>
              is exact only if
              <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION ALL</code></a>
              is used. If <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a> without
              <code class="literal">ALL</code> is used, duplicate removal occurs
              and the value of
              <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> is only
              approximate.
            </p></li><li class="listitem"><p>
              If no <code class="literal">LIMIT</code> is present in the
              <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a>,
              <code class="literal">SQL_CALC_FOUND_ROWS</code> is ignored and
              returns the number of rows in the temporary table that is
              created to process the
              <a class="link" href="sql-statements.html#union" title="13.2.10.3 UNION Clause"><code class="literal">UNION</code></a>.
</p></li></ul>
</div>
<p>
          Beyond the cases described here, the behavior of
          <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> is undefined (for
          example, its value following a
          <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement that fails
          with an error).
</p>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Important
</div>
<p>
            <a class="link" href="functions.html#function_found-rows"><code class="literal">FOUND_ROWS()</code></a> is not
            replicated reliably using statement-based replication. This
            function is automatically replicated using row-based
            replication.
</p>
</div>
</li><li class="listitem"><a name="function_icu-version"></a><p>
          <a class="link" href="functions.html#function_icu-version"><code class="literal">ICU_VERSION()</code></a>
        </p><a class="indexterm" name="idm46444324522464"></a><p>
          The version of the International Components for Unicode (ICU)
          library used to support regular expression operations (see
          <a class="xref" href="functions.html#regexp" title="12.7.2 Regular Expressions">Section 12.7.2, “Regular Expressions”</a>). This function is primarily intended
          for use in test cases.
        </p></li><li class="listitem"><a name="function_last-insert-id"></a><p>
          <a class="indexterm" name="idm46444324517168"></a>

          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>,
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          With no argument,
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> returns a
          <code class="literal">BIGINT UNSIGNED</code> (64-bit) value representing
          the first automatically generated value successfully inserted
          for an <code class="literal">AUTO_INCREMENT</code> column as a result of
          the most recently executed
          <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> statement. The value of
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> remains
          unchanged if no rows are successfully inserted.
        </p><p>
          With an argument,
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> returns an
          unsigned integer.
        </p><p>
          For example, after inserting a row that generates an
          <code class="literal">AUTO_INCREMENT</code> value, you can get the value
          like this:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT LAST_INSERT_ID();</code></strong>
        -&gt; 195
</pre><p>
          The currently executing statement does not affect the value of
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>. Suppose that
          you generate an <code class="literal">AUTO_INCREMENT</code> value with
          one statement, and then refer to
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> in a
          multiple-row <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> statement
          that inserts rows into a table with its own
          <code class="literal">AUTO_INCREMENT</code> column. The value of
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> will remain
          stable in the second statement; its value for the second and
          later rows is not affected by the earlier row insertions.
          (However, if you mix references to
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> and
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID(<em class="replaceable"><code>expr</code></em>)</code></a>,
          the effect is undefined.)
        </p><p>
          If the previous statement returned an error, the value of
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> is undefined.
          For transactional tables, if the statement is rolled back due
          to an error, the value of
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> is left
          undefined. For manual
          <a class="link" href="sql-statements.html#commit" title="13.3.1 START TRANSACTION, COMMIT, and ROLLBACK Statements"><code class="literal">ROLLBACK</code></a>,
          the value of <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>
          is not restored to that before the transaction; it remains as
          it was at the point of the
          <a class="link" href="sql-statements.html#commit" title="13.3.1 START TRANSACTION, COMMIT, and ROLLBACK Statements"><code class="literal">ROLLBACK</code></a>.
        </p><p>
          Within the body of a stored routine (procedure or function) or
          a trigger, the value of
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> changes the
          same way as for statements executed outside the body of these
          kinds of objects. The effect of a stored routine or trigger
          upon the value of
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> that is seen
          by following statements depends on the kind of routine:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If a stored procedure executes statements that change the
              value of <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>,
              the changed value is seen by statements that follow the
              procedure call.
            </p></li><li class="listitem"><p>
              For stored functions and triggers that change the value,
              the value is restored when the function or trigger ends,
              so following statements will not see a changed value.
</p></li></ul>
</div>
<p>
          The ID that was generated is maintained in the server on a
          <span class="emphasis"><em>per-connection basis</em></span>. This means that the
          value returned by the function to a given client is the first
          <code class="literal">AUTO_INCREMENT</code> value generated for most
          recent statement affecting an
          <code class="literal">AUTO_INCREMENT</code> column <span class="emphasis"><em>by that
          client</em></span>. This value cannot be affected by other
          clients, even if they generate
          <code class="literal">AUTO_INCREMENT</code> values of their own. This
          behavior ensures that each client can retrieve its own ID
          without concern for the activity of other clients, and without
          the need for locks or transactions.
        </p><p>
          The value of <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>
          is not changed if you set the
          <code class="literal">AUTO_INCREMENT</code> column of a row to a
          non-<span class="quote">“<span class="quote">magic</span>”</span> value (that is, a value that is not
          <code class="literal">NULL</code> and not <code class="literal">0</code>).
</p>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Important
</div>
<p>
            If you insert multiple rows using a single
            <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> statement,
            <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> returns the
            value generated for the <span class="emphasis"><em>first</em></span> inserted
            row <span class="emphasis"><em>only</em></span>. The reason for this is to
            make it possible to reproduce easily the same
            <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> statement against some
            other server.
</p>
</div>
<p>
          For example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>USE test;</code></strong>

mysql&gt; <strong class="userinput"><code>CREATE TABLE t (</code></strong>
       <strong class="userinput"><code>id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,</code></strong>
       <strong class="userinput"><code>name VARCHAR(10) NOT NULL</code></strong>
       <strong class="userinput"><code>);</code></strong>

mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES (NULL, 'Bob');</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT * FROM t;</code></strong>
+----+------+
| id | name |
+----+------+
|  1 | Bob  |
+----+------+

mysql&gt; <strong class="userinput"><code>SELECT LAST_INSERT_ID();</code></strong>
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+

mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES</code></strong>
       <strong class="userinput"><code>(NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT * FROM t;</code></strong>
+----+------+
| id | name |
+----+------+
|  1 | Bob  |
|  2 | Mary |
|  3 | Jane |
|  4 | Lisa |
+----+------+

mysql&gt; <strong class="userinput"><code>SELECT LAST_INSERT_ID();</code></strong>
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                2 |
+------------------+
</pre><p>
          Although the second <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a>
          statement inserted three new rows into <code class="literal">t</code>,
          the ID generated for the first of these rows was
          <code class="literal">2</code>, and it is this value that is returned by
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> for the
          following <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement.
        </p><p>
          If you use <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT
          IGNORE</code></a> and the row is ignored, the
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> remains
          unchanged from the current value (or 0 is returned if the
          connection has not yet performed a successful
          <code class="literal">INSERT</code>) and, for non-transactional tables,
          the <code class="literal">AUTO_INCREMENT</code> counter is not
          incremented. For <code class="literal">InnoDB</code> tables, the
          <code class="literal">AUTO_INCREMENT</code> counter is incremented if
          <a class="link" href="innodb-storage-engine.html#sysvar_innodb_autoinc_lock_mode"><code class="literal">innodb_autoinc_lock_mode</code></a> is
          set to <code class="literal">1</code> or <code class="literal">2</code>, as
          demonstrated in the following example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>USE test;</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT @@innodb_autoinc_lock_mode;</code></strong>
+----------------------------+
| @@innodb_autoinc_lock_mode |
+----------------------------+
|                          1 |
+----------------------------+

mysql&gt; <strong class="userinput"><code>CREATE TABLE `t` (</code></strong>
       <strong class="userinput"><code>`id` INT(11) NOT NULL AUTO_INCREMENT,</code></strong>
       <strong class="userinput"><code>`val` INT(11) DEFAULT NULL,</code></strong>
       <strong class="userinput"><code>PRIMARY KEY (`id`),</code></strong>
       <strong class="userinput"><code>UNIQUE KEY `i1` (`val`)</code></strong>
       <strong class="userinput"><code>) ENGINE=InnoDB DEFAULT CHARSET=latin1;</code></strong>

# Insert two rows

mysql&gt; <strong class="userinput"><code>INSERT INTO t (val) VALUES (1),(2);</code></strong>

# With auto_increment_offset=1, the inserted rows
# result in an AUTO_INCREMENT value of 3

mysql&gt; <strong class="userinput"><code>SHOW CREATE TABLE t\G</code></strong>
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `val` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `i1` (`val`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1

# LAST_INSERT_ID() returns the first automatically generated
# value that is successfully inserted for the AUTO_INCREMENT column

mysql&gt; <strong class="userinput"><code>SELECT LAST_INSERT_ID();</code></strong>
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+

# The attempted insertion of duplicate rows fail but errors are ignored

mysql&gt; <strong class="userinput"><code>INSERT IGNORE INTO t (val) VALUES (1),(2);</code></strong>
Query OK, 0 rows affected (0.00 sec)
Records: 2  Duplicates: 2  Warnings: 0

# With innodb_autoinc_lock_mode=1, the AUTO_INCREMENT counter
# is incremented for the ignored rows

mysql&gt; <strong class="userinput"><code>SHOW CREATE TABLE t\G</code></strong>
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `val` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `i1` (`val`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1

# The LAST_INSERT_ID is unchanged because the previous insert was unsuccessful

mysql&gt; <strong class="userinput"><code>SELECT LAST_INSERT_ID();</code></strong>
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+
</pre><p>
          For more information, see
          <a class="xref" href="innodb-storage-engine.html#innodb-auto-increment-handling" title="15.6.1.6 AUTO_INCREMENT Handling in InnoDB">Section 15.6.1.6, “AUTO_INCREMENT Handling in InnoDB”</a>.
        </p><p>
          <a class="indexterm" name="idm46444324423008"></a>

          If <em class="replaceable"><code>expr</code></em> is given as an argument to
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>, the value of
          the argument is returned by the function and is remembered as
          the next value to be returned by
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>. This can be
          used to simulate sequences:
</p>
<div class="orderedlist">
<ol class="orderedlist" type="1"><li class="listitem"><p>
              Create a table to hold the sequence counter and initialize
              it:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE sequence (id INT NOT NULL);</code></strong>
mysql&gt; <strong class="userinput"><code>INSERT INTO sequence VALUES (0);</code></strong>
</pre></li><li class="listitem"><p>
              Use the table to generate sequence numbers like this:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE sequence SET id=LAST_INSERT_ID(id+1);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT LAST_INSERT_ID();</code></strong>
</pre><p>
              The <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement
              increments the sequence counter and causes the next call
              to <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a> to
              return the updated value. The
              <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement retrieves
              that value. The
              <a class="link" href="connectors-apis.html#mysql-insert-id" title="28.7.6.38 mysql_insert_id()"><code class="literal">mysql_insert_id()</code></a> C API
              function can also be used to get the value. See
              <a class="xref" href="connectors-apis.html#mysql-insert-id" title="28.7.6.38 mysql_insert_id()">Section 28.7.6.38, “mysql_insert_id()”</a>.
</p></li></ol>
</div>
<p>
          You can generate sequences without calling
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID()</code></a>, but the
          utility of using the function this way is that the ID value is
          maintained in the server as the last automatically generated
          value. It is multi-user safe because multiple clients can
          issue the <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statement and
          get their own sequence value with the
          <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statement (or
          <a class="link" href="connectors-apis.html#mysql-insert-id" title="28.7.6.38 mysql_insert_id()"><code class="literal">mysql_insert_id()</code></a>), without
          affecting or being affected by other clients that generate
          their own sequence values.
        </p><p>
          Note that <a class="link" href="connectors-apis.html#mysql-insert-id" title="28.7.6.38 mysql_insert_id()"><code class="literal">mysql_insert_id()</code></a> is
          only updated after <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> and
          <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statements, so you
          cannot use the C API function to retrieve the value for
          <a class="link" href="functions.html#function_last-insert-id"><code class="literal">LAST_INSERT_ID(<em class="replaceable"><code>expr</code></em>)</code></a>
          after executing other SQL statements like
          <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> or
          <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>.
        </p></li><li class="listitem"><a name="function_roles-graphml"></a><p>
          <a class="indexterm" name="idm46444324387760"></a>

          <a class="link" href="functions.html#function_roles-graphml"><code class="literal">ROLES_GRAPHML()</code></a>
        </p><p>
          Returns a <code class="literal">utf8</code> string containing a GraphML
          document representing memory role subgraphs. The
          <a class="link" href="security.html#priv_role-admin"><code class="literal">ROLE_ADMIN</code></a> privilege (or the
          deprecated <a class="link" href="security.html#priv_super"><code class="literal">SUPER</code></a> privilege) is
          required to see content in the
          <code class="literal">&lt;graphml&gt;</code> element. Otherwise, the
          result shows only an empty element:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ROLES_GRAPHML();</code></strong>
+---------------------------------------------------+
| ROLES_GRAPHML()                                   |
+---------------------------------------------------+
| &lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;graphml /&gt; |
+---------------------------------------------------+
</pre></li><li class="listitem"><a name="function_row-count"></a><p>
          <a class="indexterm" name="idm46444324375920"></a>

          <a class="link" href="functions.html#function_row-count"><code class="literal">ROW_COUNT()</code></a>
        </p><p>
          <code class="literal">ROW_COUNT()</code> returns a value as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              DDL statements: 0. This applies to statements such as
              <a class="link" href="sql-statements.html#create-table" title="13.1.20 CREATE TABLE Statement"><code class="literal">CREATE TABLE</code></a> or
              <a class="link" href="sql-statements.html#drop-table" title="13.1.32 DROP TABLE Statement"><code class="literal">DROP TABLE</code></a>.
            </p></li><li class="listitem"><p>
              DML statements other than
              <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>: The number of
              affected rows. This applies to statements such as
              <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a>,
              <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a>, or
              <a class="link" href="sql-statements.html#delete" title="13.2.2 DELETE Statement"><code class="literal">DELETE</code></a> (as before), but now
              also to statements such as <a class="link" href="sql-statements.html#alter-table" title="13.1.9 ALTER TABLE Statement"><code class="literal">ALTER
              TABLE</code></a> and <a class="link" href="sql-statements.html#load-data" title="13.2.7 LOAD DATA Statement"><code class="literal">LOAD
              DATA</code></a>.
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>: -1 if the statement
              returns a result set, or the number of rows
              <span class="quote">“<span class="quote">affected</span>”</span> if it does not. For example, for
              <code class="literal">SELECT * FROM t1</code>,
              <a class="link" href="functions.html#function_row-count"><code class="literal">ROW_COUNT()</code></a> returns -1. For
              <code class="literal">SELECT * FROM t1 INTO OUTFILE
              '<em class="replaceable"><code>file_name</code></em>'</code>,
              <a class="link" href="functions.html#function_row-count"><code class="literal">ROW_COUNT()</code></a> returns the
              number of rows written to the file.
            </p></li><li class="listitem"><p>
              <a class="link" href="sql-statements.html#signal" title="13.6.7.5 SIGNAL Statement"><code class="literal">SIGNAL</code></a> statements: 0.
</p></li></ul>
</div>
<p>
          For <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> statements, the
          affected-rows value by default is the number of rows actually
          changed. If you specify the
          <code class="literal">CLIENT_FOUND_ROWS</code> flag to
          <a class="link" href="connectors-apis.html#mysql-real-connect" title="28.7.6.54 mysql_real_connect()"><code class="literal">mysql_real_connect()</code></a> when
          connecting to <a class="link" href="programs.html#mysqld" title="4.3.1 mysqld — The MySQL Server"><span class="command"><strong>mysqld</strong></span></a>, the affected-rows
          value is the number of rows <span class="quote">“<span class="quote">found</span>”</span>; that is,
          matched by the <code class="literal">WHERE</code> clause.
        </p><p>
          For <a class="link" href="sql-statements.html#replace" title="13.2.9 REPLACE Statement"><code class="literal">REPLACE</code></a> statements, the
          affected-rows value is 2 if the new row replaced an old row,
          because in this case, one row was inserted after the duplicate
          was deleted.
        </p><p>
          For
          <a class="link" href="sql-statements.html#insert-on-duplicate" title="13.2.6.2 INSERT ... ON DUPLICATE KEY UPDATE Statement"><code class="literal">INSERT
          ... ON DUPLICATE KEY UPDATE</code></a> statements, the
          affected-rows value per row is 1 if the row is inserted as a
          new row, 2 if an existing row is updated, and 0 if an existing
          row is set to its current values. If you specify the
          <code class="literal">CLIENT_FOUND_ROWS</code> flag, the affected-rows
          value is 1 (not 0) if an existing row is set to its current
          values.
        </p><p>
          The <a class="link" href="functions.html#function_row-count"><code class="literal">ROW_COUNT()</code></a> value is
          similar to the value from the
          <a class="link" href="connectors-apis.html#mysql-affected-rows" title="28.7.6.1 mysql_affected_rows()"><code class="literal">mysql_affected_rows()</code></a> C API
          function and the row count that the <a class="link" href="programs.html#mysql" title="4.5.1 mysql — The MySQL Command-Line Client"><span class="command"><strong>mysql</strong></span></a>
          client displays following statement execution.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES(1),(2),(3);</code></strong>
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT ROW_COUNT();</code></strong>
+-------------+
| ROW_COUNT() |
+-------------+
|           3 |
+-------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>DELETE FROM t WHERE i IN(1,2);</code></strong>
Query OK, 2 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT ROW_COUNT();</code></strong>
+-------------+
| ROW_COUNT() |
+-------------+
|           2 |
+-------------+
1 row in set (0.00 sec)
</pre>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Important
</div>
<p>
            <a class="link" href="functions.html#function_row-count"><code class="literal">ROW_COUNT()</code></a> is not replicated
            reliably using statement-based replication. This function is
            automatically replicated using row-based replication.
</p>
</div>
</li><li class="listitem"><a name="function_schema"></a><p>
          <a class="indexterm" name="idm46444324324032"></a>

          <a class="link" href="functions.html#function_schema"><code class="literal">SCHEMA()</code></a>
        </p><p>
          This function is a synonym for
          <a class="link" href="functions.html#function_database"><code class="literal">DATABASE()</code></a>.
        </p></li><li class="listitem"><a name="function_session-user"></a><p>
          <a class="indexterm" name="idm46444324315968"></a>

          <a class="link" href="functions.html#function_session-user"><code class="literal">SESSION_USER()</code></a>
        </p><p>
          <a class="link" href="functions.html#function_session-user"><code class="literal">SESSION_USER()</code></a> is a synonym for
          <a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a>.
        </p></li><li class="listitem"><a name="function_system-user"></a><p>
          <a class="indexterm" name="idm46444324306720"></a>

          <a class="link" href="functions.html#function_system-user"><code class="literal">SYSTEM_USER()</code></a>
        </p><p>
          <a class="link" href="functions.html#function_system-user"><code class="literal">SYSTEM_USER()</code></a> is a synonym for
          <a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            The <a class="link" href="functions.html#function_system-user"><code class="literal">SYSTEM_USER()</code></a> function is
            distinct from the <a class="link" href="security.html#priv_system-user"><code class="literal">SYSTEM_USER</code></a>
            privilege. The former returns the current MySQL account
            name. The latter distinguishes the system user and regular
            user account categories (see
            <a class="xref" href="security.html#account-categories" title="6.2.11 Account Categories">Section 6.2.11, “Account Categories”</a>).
</p>
</div>
</li><li class="listitem"><a name="function_user"></a><p>
          <a class="indexterm" name="idm46444324293328"></a>

          <a class="link" href="functions.html#function_user"><code class="literal">USER()</code></a>
        </p><p>
          Returns the current MySQL user name and host name as a string
          in the <code class="literal">utf8</code> character set.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT USER();</code></strong>
        -&gt; 'davida@localhost'
</pre><p>
          The value indicates the user name you specified when
          connecting to the server, and the client host from which you
          connected. The value can be different from that of
          <a class="link" href="functions.html#function_current-user"><code class="literal">CURRENT_USER()</code></a>.
        </p></li><li class="listitem"><a name="function_version"></a><p>
          <a class="indexterm" name="idm46444324281632"></a>

          <a class="link" href="functions.html#function_version"><code class="literal">VERSION()</code></a>
        </p><p>
          Returns a string that indicates the MySQL server version. The
          string uses the <code class="literal">utf8</code> character set. The
          value might have a suffix in addition to the version number.
          See the description of the
          <a class="link" href="server-administration.html#sysvar_version"><code class="literal">version</code></a> system variable in
          <a class="xref" href="server-administration.html#server-system-variables" title="5.1.8 Server System Variables">Section 5.1.8, “Server System Variables”</a>.
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT VERSION();</code></strong>
        -&gt; '8.0.22-standard'
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="spatial-analysis-functions"></a>12.16 Spatial Analysis Functions</h2>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#spatial-function-reference">12.16.1 Spatial Function Reference</a></span></dt><dt><span class="section"><a href="functions.html#spatial-function-argument-handling">12.16.2 Argument Handling by Spatial Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-wkt-functions">12.16.3 Functions That Create Geometry Values from WKT Values</a></span></dt><dt><span class="section"><a href="functions.html#gis-wkb-functions">12.16.4 Functions That Create Geometry Values from WKB Values</a></span></dt><dt><span class="section"><a href="functions.html#gis-mysql-specific-functions">12.16.5 MySQL-Specific Functions That Create Geometry Values</a></span></dt><dt><span class="section"><a href="functions.html#gis-format-conversion-functions">12.16.6 Geometry Format Conversion Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-property-functions">12.16.7 Geometry Property Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-operator-functions">12.16.8 Spatial Operator Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-relation-functions">12.16.9 Functions That Test Spatial Relations Between Geometry Objects</a></span></dt><dt><span class="section"><a href="functions.html#spatial-geohash-functions">12.16.10 Spatial Geohash Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-geojson-functions">12.16.11 Spatial GeoJSON Functions</a></span></dt><dt><span class="section"><a href="functions.html#spatial-convenience-functions">12.16.12 Spatial Convenience Functions</a></span></dt></dl>
</div>
<p>
    MySQL provides functions to perform various operations on spatial
    data. These functions can be grouped into several major categories
    according to the type of operation they perform:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
        Functions that create geometries in various formats (WKT, WKB,
        internal)
      </p></li><li class="listitem"><p>
        Functions that convert geometries between formats
      </p></li><li class="listitem"><p>
        Functions that access qualitative or quantitative properties of
        a geometry
      </p></li><li class="listitem"><p>
        Functions that describe relations between two geometries
      </p></li><li class="listitem"><p>
        Functions that create new geometries from existing ones
</p></li></ul>
</div>
<p>
    For general background about MySQL support for using spatial data,
    see <a class="xref" href="data-types.html#spatial-types" title="11.4 Spatial Data Types">Section 11.4, “Spatial Data Types”</a>.
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="spatial-function-reference"></a>12.16.1 Spatial Function Reference</h3>
</div>
</div>
</div>
<a class="indexterm" name="idm46444324259648"></a><p>
      The following table lists each spatial function and provides a
      short description of each one.
</p>
<div class="table">
<a name="idm46444324258064"></a><p class="title"><b>Table 12.20 Spatial Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists all spatial functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a></td>
<td>
      Construct geometry collection from geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection()</code></a></td>
<td>
      Construct geometry collection from geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_linestring"><code class="literal">LineString()</code></a></td>
<td>
      Construct LineString from Point values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrcontains"><code class="literal">MBRContains()</code></a></td>
<td>
      Whether MBR of one geometry contains MBR of another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrcoveredby"><code class="literal">MBRCoveredBy()</code></a></td>
<td>
      Whether one MBR is covered by another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrcovers"><code class="literal">MBRCovers()</code></a></td>
<td>
      Whether one MBR covers another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrdisjoint"><code class="literal">MBRDisjoint()</code></a></td>
<td>
      Whether MBRs of two geometries are disjoint
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrequals"><code class="literal">MBREquals()</code></a></td>
<td>
      Whether MBRs of two geometries are equal
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrintersects"><code class="literal">MBRIntersects()</code></a></td>
<td>
      Whether MBRs of two geometries intersect
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbroverlaps"><code class="literal">MBROverlaps()</code></a></td>
<td>
      Whether MBRs of two geometries overlap
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrtouches"><code class="literal">MBRTouches()</code></a></td>
<td>
      Whether MBRs of two geometries touch
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_mbrwithin"><code class="literal">MBRWithin()</code></a></td>
<td>
      Whether MBR of one geometry is within MBR of another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_multilinestring"><code class="literal">MultiLineString()</code></a></td>
<td>
      Contruct MultiLineString from LineString values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_multipoint"><code class="literal">MultiPoint()</code></a></td>
<td>
      Construct MultiPoint from Point values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_multipolygon"><code class="literal">MultiPolygon()</code></a></td>
<td>
      Construct MultiPolygon from Polygon values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_point"><code class="literal">Point()</code></a></td>
<td>
      Construct Point from coordinates
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_polygon"><code class="literal">Polygon()</code></a></td>
<td>
      Construct Polygon from LineString arguments
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-area"><code class="literal">ST_Area()</code></a></td>
<td>
      Return Polygon or MultiPolygon area
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-asbinary"><code class="literal">ST_AsBinary()</code>, <code class="literal">ST_AsWKB()</code></a></td>
<td>
      Convert from internal geometry format to WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-asgeojson"><code class="literal">ST_AsGeoJSON()</code></a></td>
<td>
      Generate GeoJSON object from geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsText()</code>, <code class="literal">ST_AsWKT()</code></a></td>
<td>
      Convert from internal geometry format to WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a></td>
<td>
      Return geometry of points within given distance from geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy()</code></a></td>
<td>
      Produce strategy option for ST_Buffer()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-centroid"><code class="literal">ST_Centroid()</code></a></td>
<td>
      Return centroid as a point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-contains"><code class="literal">ST_Contains()</code></a></td>
<td>
      Whether one geometry contains another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-convexhull"><code class="literal">ST_ConvexHull()</code></a></td>
<td>
      Return convex hull of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-crosses"><code class="literal">ST_Crosses()</code></a></td>
<td>
      Whether one geometry crosses another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-difference"><code class="literal">ST_Difference()</code></a></td>
<td>
      Return point set difference of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-dimension"><code class="literal">ST_Dimension()</code></a></td>
<td>
      Dimension of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-disjoint"><code class="literal">ST_Disjoint()</code></a></td>
<td>
      Whether one geometry is disjoint from another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a></td>
<td>
      The distance of one geometry from another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-distance-sphere"><code class="literal">ST_Distance_Sphere()</code></a></td>
<td>
      Minimum distance on earth between two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-endpoint"><code class="literal">ST_EndPoint()</code></a></td>
<td>
      End Point of LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-envelope"><code class="literal">ST_Envelope()</code></a></td>
<td>
      Return MBR of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-equals"><code class="literal">ST_Equals()</code></a></td>
<td>
      Whether one geometry is equal to another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-exteriorring"><code class="literal">ST_ExteriorRing()</code></a></td>
<td>
      Return exterior ring of Polygon
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geohash"><code class="literal">ST_GeoHash()</code></a></td>
<td>
      Produce a geohash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomcollfromtext"><code class="literal">ST_GeomCollFromText()</code>, <code class="literal">ST_GeometryCollectionFromText()</code>, <code class="literal">ST_GeomCollFromTxt()</code></a></td>
<td>
      Return geometry collection from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomcollfromwkb"><code class="literal">ST_GeomCollFromWKB()</code>, <code class="literal">ST_GeometryCollectionFromWKB()</code></a></td>
<td>
      Return geometry collection from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geometryn"><code class="literal">ST_GeometryN()</code></a></td>
<td>
      Return N-th geometry from geometry collection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geometrytype"><code class="literal">ST_GeometryType()</code></a></td>
<td>
      Return name of geometry type
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomfromgeojson"><code class="literal">ST_GeomFromGeoJSON()</code></a></td>
<td>
      Generate geometry from GeoJSON object
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code>, <code class="literal">ST_GeometryFromText()</code></a></td>
<td>
      Return geometry from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-geomfromwkb"><code class="literal">ST_GeomFromWKB()</code>, <code class="literal">ST_GeometryFromWKB()</code></a></td>
<td>
      Return geometry from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-interiorringn"><code class="literal">ST_InteriorRingN()</code></a></td>
<td>
      Return N-th interior ring of Polygon
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-intersection"><code class="literal">ST_Intersection()</code></a></td>
<td>
      Return point set intersection of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-intersects"><code class="literal">ST_Intersects()</code></a></td>
<td>
      Whether one geometry intersects another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-isclosed"><code class="literal">ST_IsClosed()</code></a></td>
<td>
      Whether a geometry is closed and simple
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-isempty"><code class="literal">ST_IsEmpty()</code></a></td>
<td>
      Placeholder function
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-issimple"><code class="literal">ST_IsSimple()</code></a></td>
<td>
      Whether a geometry is simple
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-isvalid"><code class="literal">ST_IsValid()</code></a></td>
<td>
      Whether a geometry is valid
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-latfromgeohash"><code class="literal">ST_LatFromGeoHash()</code></a></td>
<td>
      Return latitude from geohash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-latitude"><code class="literal">ST_Latitude()</code></a> (introduced 8.0.12)</td>
<td>
      Return latitude of Point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-length"><code class="literal">ST_Length()</code></a></td>
<td>
      Return length of LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-linefromtext"><code class="literal">ST_LineFromText()</code>, <code class="literal">ST_LineStringFromText()</code></a></td>
<td>
      Construct LineString from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-linefromwkb"><code class="literal">ST_LineFromWKB()</code>, <code class="literal">ST_LineStringFromWKB()</code></a></td>
<td>
      Construct LineString from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-longfromgeohash"><code class="literal">ST_LongFromGeoHash()</code></a></td>
<td>
      Return longitude from geohash value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-longitude"><code class="literal">ST_Longitude()</code></a> (introduced 8.0.12)</td>
<td>
      Return longitude of Point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-makeenvelope"><code class="literal">ST_MakeEnvelope()</code></a></td>
<td>
      Rectangle around two points
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mlinefromtext"><code class="literal">ST_MLineFromText()</code>, <code class="literal">ST_MultiLineStringFromText()</code></a></td>
<td>
      Construct MultiLineString from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mlinefromwkb"><code class="literal">ST_MLineFromWKB()</code>, <code class="literal">ST_MultiLineStringFromWKB()</code></a></td>
<td>
      Construct MultiLineString from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpointfromtext"><code class="literal">ST_MPointFromText()</code>, <code class="literal">ST_MultiPointFromText()</code></a></td>
<td>
      Construct MultiPoint from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpointfromwkb"><code class="literal">ST_MPointFromWKB()</code>, <code class="literal">ST_MultiPointFromWKB()</code></a></td>
<td>
      Construct MultiPoint from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpolyfromtext"><code class="literal">ST_MPolyFromText()</code>, <code class="literal">ST_MultiPolygonFromText()</code></a></td>
<td>
      Construct MultiPolygon from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-mpolyfromwkb"><code class="literal">ST_MPolyFromWKB()</code>, <code class="literal">ST_MultiPolygonFromWKB()</code></a></td>
<td>
      Construct MultiPolygon from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-numgeometries"><code class="literal">ST_NumGeometries()</code></a></td>
<td>
      Return number of geometries in geometry collection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-numinteriorrings"><code class="literal">ST_NumInteriorRing()</code>, <code class="literal">ST_NumInteriorRings()</code></a></td>
<td>
      Return number of interior rings in Polygon
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-numpoints"><code class="literal">ST_NumPoints()</code></a></td>
<td>
      Return number of points in LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-overlaps"><code class="literal">ST_Overlaps()</code></a></td>
<td>
      Whether one geometry overlaps another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointfromgeohash"><code class="literal">ST_PointFromGeoHash()</code></a></td>
<td>
      Convert geohash value to POINT value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointfromtext"><code class="literal">ST_PointFromText()</code></a></td>
<td>
      Construct Point from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointfromwkb"><code class="literal">ST_PointFromWKB()</code></a></td>
<td>
      Construct Point from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-pointn"><code class="literal">ST_PointN()</code></a></td>
<td>
      Return N-th point from LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-polyfromtext"><code class="literal">ST_PolyFromText()</code>, <code class="literal">ST_PolygonFromText()</code></a></td>
<td>
      Construct Polygon from WKT
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-polyfromwkb"><code class="literal">ST_PolyFromWKB()</code>, <code class="literal">ST_PolygonFromWKB()</code></a></td>
<td>
      Construct Polygon from WKB
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-simplify"><code class="literal">ST_Simplify()</code></a></td>
<td>
      Return simplified geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a></td>
<td>
      Return spatial reference system ID for geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-startpoint"><code class="literal">ST_StartPoint()</code></a></td>
<td>
      Start Point of LineString
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-swapxy"><code class="literal">ST_SwapXY()</code></a></td>
<td>
      Return argument with X/Y coordinates swapped
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-symdifference"><code class="literal">ST_SymDifference()</code></a></td>
<td>
      Return point set symmetric difference of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-touches"><code class="literal">ST_Touches()</code></a></td>
<td>
      Whether one geometry touches another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform()</code></a> (introduced 8.0.13)</td>
<td>
      Transform coordinates of geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-union"><code class="literal">ST_Union()</code></a></td>
<td>
      Return point set union of two geometries
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate()</code></a></td>
<td>
      Return validated geometry
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-within"><code class="literal">ST_Within()</code></a></td>
<td>
      Whether one geometry is within another
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-x"><code class="literal">ST_X()</code></a></td>
<td>
      Return X coordinate of Point
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_st-y"><code class="literal">ST_Y()</code></a></td>
<td>
      Return Y coordinate of Point
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="spatial-function-argument-handling"></a>12.16.2 Argument Handling by Spatial Functions</h3>

</div>

</div>

</div>
<p>
      Spatial values, or geometries, have the properties described at
      <a class="xref" href="data-types.html#gis-class-geometry" title="11.4.2.2 Geometry Class">Section 11.4.2.2, “Geometry Class”</a>. The following discussion
      lists general spatial function argument-handling characteristics.
      Specific functions or groups of functions may have additional
      argument-handling characteristics, as discussed in the sections
      where those function descriptions occur.
    </p><p>
      Spatial functions are defined only for valid geometry values.
    </p><a class="indexterm" name="idm46444323953344"></a><p>
      The spatial reference identifier (SRID) of a geometry identifies
      the coordinate space in which the geometry is defined. In MySQL,
      the SRID value is an integer associated with the geometry value.
      The maximum usable SRID value is
      2<sup>32</sup>−1. If a larger value is
      given, only the lower 32 bits are used.
    </p><p>
      SRID 0 represents an infinite flat Cartesian plane with no units
      assigned to its axes. To ensure SRID 0 behavior, create geometry
      values using SRID 0. SRID 0 is the default for new geometry values
      if no SRID is specified.
    </p><p>
      Geometry values produced by any spatial function inherit the SRID
      of the geometry arguments.
    </p><p>
      Spatial functions that take multiple geometry arguments require
      those arguments to have the same SRID value (that is, same value
      in the lower 32 bits). Assuming equal SRIDs, spatial functions do
      nothing with them after performing the equality check; geometry
      values are implicitly handled using Cartesian coordinates (SRID
      0). If a spatial function returns
      <a class="link" href="error-handling.html#error_er_gis_different_srids"><code class="literal">ER_GIS_DIFFERENT_SRIDS</code></a>, it means
      that the geometry arguments did not all have the same SRID. You
      must modify them to have the same SRID.
    </p><p>
      The <a class="ulink" href="http://www.opengeospatial.org" target="_top">Open Geospatial
      Consortium</a> guidelines require that input polygons already
      be closed, so unclosed polygons are rejected as invalid rather
      than being closed.
    </p><p>
      Empty geometry-collection handling is as follows: An empty WKT
      input geometry collection may be specified as
      <code class="literal">'GEOMETRYCOLLECTION()'</code>. This is also the output
      WKT resulting from a spatial operation that produces an empty
      geometry collection.
    </p><p>
      During parsing of a nested geometry collection, the collection is
      flattened and its basic components are used in various GIS
      operations to compute results. This provides additional
      flexibility to users because it is unnecessary to be concerned
      about the uniqueness of geometry data. Nested geometry collections
      may be produced from nested GIS function calls without having to
      be explicitly flattened first.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="gis-wkt-functions"></a>12.16.3 Functions That Create Geometry Values from WKT Values</h3>

</div>

</div>

</div>
<p>
      These functions take as arguments a Well-Known Text (WKT)
      representation and, optionally, a spatial reference system
      identifier (SRID). They return the corresponding geometry. For a
      description of WKT format, see <a class="xref" href="data-types.html#gis-wkt-format" title="Well-Known Text (WKT) Format">Well-Known Text (WKT) Format</a>.
    </p><p>
      Functions in this section detect arguments in either Cartesian or
      geographic spatial reference systems (SRSs), and return results
      appropriate to the SRS.
    </p><p>
      <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code></a> accepts a WKT
      value of any geometry type as its first argument. Other functions
      provide type-specific construction functions for construction of
      geometry values of each geometry type.
    </p><p>
      Functions such as
      <a class="link" href="functions.html#function_st-mpointfromtext"><code class="literal">ST_MPointFromText()</code></a> and
      <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code></a> that accept
      WKT-format representations of <code class="literal">MultiPoint</code> values
      permit individual points within values to be surrounded by
      parentheses. For example, both of the following function calls are
      valid:
    </p><pre data-lang="sql" class="programlisting">ST_MPointFromText('MULTIPOINT (1 1, 2 2, 3 3)')
ST_MPointFromText('MULTIPOINT ((1 1), (2 2), (3 3))')</pre><p>
      Functions such as <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code></a>
      that accept WKT geometry collection arguments understand both
      OpenGIS <code class="literal">'GEOMETRYCOLLECTION EMPTY'</code> standard
      syntax and MySQL <code class="literal">'GEOMETRYCOLLECTION()'</code>
      nonstandard syntax. Functions such as
      <a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsWKT()</code></a>
      that produce WKT values produce <code class="literal">'GEOMETRYCOLLECTION
      EMPTY'</code> standard syntax:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s1 = ST_GeomFromText('GEOMETRYCOLLECTION()');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @s2 = ST_GeomFromText('GEOMETRYCOLLECTION EMPTY');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsWKT(@s1), ST_AsWKT(@s2);</code></strong>
+--------------------------+--------------------------+
| ST_AsWKT(@s1)            | ST_AsWKT(@s2)            |
+--------------------------+--------------------------+
| GEOMETRYCOLLECTION EMPTY | GEOMETRYCOLLECTION EMPTY |
+--------------------------+--------------------------+
</pre><p>
      Unless otherwise specified, functions in this section handle their
      arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If any geometry argument is <code class="literal">NULL</code> or is not
          a syntactically well-formed geometry, or if the SRID argument
          is <code class="literal">NULL</code>, the return value is
          <code class="literal">NULL</code>.
        </p></li><li class="listitem"><p>
          By default, geographic coordinates (latitude, longitude) are
          interpreted as in the order specified by the spatial reference
          system of geometry arguments. An optional
          <em class="replaceable"><code>options</code></em> argument may be given to
          override the default axis order. <code class="option">options</code>
          consists of a list of comma-separated
          <code class="literal"><em class="replaceable"><code>key</code></em>=<em class="replaceable"><code>value</code></em></code>.
          The only permitted <em class="replaceable"><code>key</code></em> value is
          <code class="literal">axis-order</code>, with permitted values of
          <code class="literal">lat-long</code>, <code class="literal">long-lat</code> and
          <code class="literal">srid-defined</code> (the default).
        </p><p>
          If the <em class="replaceable"><code>options</code></em> argument is
          <code class="literal">NULL</code>, the return value is
          <code class="literal">NULL</code>. If the
          <em class="replaceable"><code>options</code></em> argument is invalid, an
          error occurs to indicate why.
        </p></li><li class="listitem"><p>
          If an SRID argument refers to an undefined spatial reference
          system (SRS), an
          <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error occurs.
        </p></li><li class="listitem"><p>
          For geographic SRS geometry arguments, if any argument has a
          longitude or latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If a longitude value is not in the range (−180,
              180], an
              <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If a latitude value is not in the range [−90, 90],
              an
              <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
              error occurs.
</p></li></ul>
</div>
<p>
          Ranges shown are in degrees. If an SRS uses another unit, the
          range uses the corresponding values in its unit. The exact
          range limits deviate slightly due to floating-point
          arithmetic.
</p></li></ul>
</div>
<p>
      These functions are available for creating geometries from WKT
      values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-geomcollfromtext"></a><p>
          <a class="indexterm" name="idm46444323897984"></a>

          <a class="indexterm" name="idm46444323896912"></a>

          <a class="link" href="functions.html#function_st-geomcollfromtext"><code class="literal">ST_GeomCollFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-geomcollfromtext"><code class="literal">ST_GeometryCollectionFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-geomcollfromtext"><code class="literal">ST_GeomCollFromTxt(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">GeometryCollection</code> value using
          its WKT representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g = "MULTILINESTRING((10 10, 11 11), (9 9, 10 10))";</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeomCollFromText(@g));</code></strong>
+--------------------------------------------+
| ST_AsText(ST_GeomCollFromText(@g))         |
+--------------------------------------------+
| MULTILINESTRING((10 10,11 11),(9 9,10 10)) |
+--------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-geomfromtext"></a><p>
          <a class="indexterm" name="idm46444323878976"></a>

          <a class="indexterm" name="idm46444323877904"></a>

          <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeometryFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a geometry value of any type using its WKT
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-linefromtext"></a><p>
          <a class="indexterm" name="idm46444323866928"></a>

          <a class="indexterm" name="idm46444323865856"></a>

          <a class="link" href="functions.html#function_st-linefromtext"><code class="literal">ST_LineFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-linefromtext"><code class="literal">ST_LineStringFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">LineString</code> value using its WKT
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-mlinefromtext"></a><p>
          <a class="indexterm" name="idm46444323854192"></a>

          <a class="indexterm" name="idm46444323853120"></a>

          <a class="link" href="functions.html#function_st-mlinefromtext"><code class="literal">ST_MLineFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-mlinefromtext"><code class="literal">ST_MultiLineStringFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">MultiLineString</code> value using
          its WKT representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-mpointfromtext"></a><p>
          <a class="indexterm" name="idm46444323841488"></a>

          <a class="indexterm" name="idm46444323840416"></a>

          <a class="link" href="functions.html#function_st-mpointfromtext"><code class="literal">ST_MPointFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-mpointfromtext"><code class="literal">ST_MultiPointFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">MultiPoint</code> value using its WKT
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-mpolyfromtext"></a><p>
          <a class="indexterm" name="idm46444323828752"></a>

          <a class="indexterm" name="idm46444323827680"></a>

          <a class="link" href="functions.html#function_st-mpolyfromtext"><code class="literal">ST_MPolyFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-mpolyfromtext"><code class="literal">ST_MultiPolygonFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">MultiPolygon</code> value using its
          WKT representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-pointfromtext"></a><p>
          <a class="indexterm" name="idm46444323816128"></a>

          <a class="link" href="functions.html#function_st-pointfromtext"><code class="literal">ST_PointFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">Point</code> value using its WKT
          representation and SRID.
        </p><p>
          <a class="link" href="functions.html#function_st-pointfromtext"><code class="literal">ST_PointFromText()</code></a> handles its
          arguments as described in the introduction to this section.
        </p></li><li class="listitem"><a name="function_st-polyfromtext"></a><p>
          <a class="indexterm" name="idm46444323805824"></a>

          <a class="indexterm" name="idm46444323804752"></a>

          <a class="link" href="functions.html#function_st-polyfromtext"><code class="literal">ST_PolyFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-polyfromtext"><code class="literal">ST_PolygonFromText(<em class="replaceable"><code>wkt</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">Polygon</code> value using its WKT
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="gis-wkb-functions"></a>12.16.4 Functions That Create Geometry Values from WKB Values</h3>

</div>

</div>

</div>
<p>
      These functions take as arguments a
      <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> containing a Well-Known Binary
      (WKB) representation and, optionally, a spatial reference system
      identifier (SRID). They return the corresponding geometry. For a
      description of WKB format, see <a class="xref" href="data-types.html#gis-wkb-format" title="Well-Known Binary (WKB) Format">Well-Known Binary (WKB) Format</a>.
    </p><p>
      Functions in this section detect arguments in either Cartesian or
      geographic spatial reference systems (SRSs), and return results
      appropriate to the SRS.
    </p><p>
      <a class="link" href="functions.html#function_st-geomfromwkb"><code class="literal">ST_GeomFromWKB()</code></a> accepts a WKB
      value of any geometry type as its first argument. Other functions
      provide type-specific construction functions for construction of
      geometry values of each geometry type.
    </p><p>
      Prior to MySQL 8.0, these functions also accepted
      geometry objects as returned by the functions in
      <a class="xref" href="functions.html#gis-mysql-specific-functions" title="12.16.5 MySQL-Specific Functions That Create Geometry Values">Section 12.16.5, “MySQL-Specific Functions That Create Geometry Values”</a>. Geometry arguments
      are no longer permitted and produce an error. To migrate calls
      from using geometry arguments to using WKB arguments, follow these
      guidelines:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Rewrite constructs such as <code class="literal">ST_GeomFromWKB(Point(0,
          0))</code> as <code class="literal">Point(0, 0)</code>.
        </p></li><li class="listitem"><p>
          Rewrite constructs such as <code class="literal">ST_GeomFromWKB(Point(0,
          0), 4326)</code> as <code class="literal">ST_SRID(Point(0, 0),
          4326)</code> or <code class="literal">ST_GeomFromWKB(ST_AsWKB(Point(0,
          0)), 4326)</code>.
</p></li></ul>
</div>
<p>
      Unless otherwise specified, functions in this section handle their
      arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If the WKB or SRID argument is <code class="literal">NULL</code>, the
          return value is <code class="literal">NULL</code>.
        </p></li><li class="listitem"><p>
          By default, geographic coordinates (latitude, longitude) are
          interpreted as in the order specified by the spatial reference
          system of geometry arguments. An optional
          <em class="replaceable"><code>options</code></em> argument may be given to
          override the default axis order. <code class="option">options</code>
          consists of a list of comma-separated
          <code class="literal"><em class="replaceable"><code>key</code></em>=<em class="replaceable"><code>value</code></em></code>.
          The only permitted <em class="replaceable"><code>key</code></em> value is
          <code class="literal">axis-order</code>, with permitted values of
          <code class="literal">lat-long</code>, <code class="literal">long-lat</code> and
          <code class="literal">srid-defined</code> (the default).
        </p><p>
          If the <em class="replaceable"><code>options</code></em> argument is
          <code class="literal">NULL</code>, the return value is
          <code class="literal">NULL</code>. If the
          <em class="replaceable"><code>options</code></em> argument is invalid, an
          error occurs to indicate why.
        </p></li><li class="listitem"><p>
          If an SRID argument refers to an undefined spatial reference
          system (SRS), an
          <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error occurs.
        </p></li><li class="listitem"><p>
          For geographic SRS geometry arguments, if any argument has a
          longitude or latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If a longitude value is not in the range (−180,
              180], an
              <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If a latitude value is not in the range [−90, 90],
              an
              <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
              error occurs.
</p></li></ul>
</div>
<p>
          Ranges shown are in degrees. If an SRS uses another unit, the
          range uses the corresponding values in its unit. The exact
          range limits deviate slightly due to floating-point
          arithmetic.
</p></li></ul>
</div>
<p>
      These functions are available for creating geometries from WKB
      values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-geomcollfromwkb"></a><p>
          <a class="indexterm" name="idm46444323756704"></a>

          <a class="indexterm" name="idm46444323755632"></a>

          <a class="link" href="functions.html#function_st-geomcollfromwkb"><code class="literal">ST_GeomCollFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-geomcollfromwkb"><code class="literal">ST_GeometryCollectionFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">GeometryCollection</code> value using
          its WKB representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-geomfromwkb"></a><p>
          <a class="indexterm" name="idm46444323743984"></a>

          <a class="indexterm" name="idm46444323742912"></a>

          <a class="link" href="functions.html#function_st-geomfromwkb"><code class="literal">ST_GeomFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-geomfromwkb"><code class="literal">ST_GeometryFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a geometry value of any type using its WKB
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-linefromwkb"></a><p>
          <a class="indexterm" name="idm46444323732048"></a>

          <a class="indexterm" name="idm46444323730976"></a>

          <a class="link" href="functions.html#function_st-linefromwkb"><code class="literal">ST_LineFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-linefromwkb"><code class="literal">ST_LineStringFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">LineString</code> value using its WKB
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-mlinefromwkb"></a><p>
          <a class="indexterm" name="idm46444323719328"></a>

          <a class="indexterm" name="idm46444323718256"></a>

          <a class="link" href="functions.html#function_st-mlinefromwkb"><code class="literal">ST_MLineFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-mlinefromwkb"><code class="literal">ST_MultiLineStringFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">MultiLineString</code> value using
          its WKB representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-mpointfromwkb"></a><p>
          <a class="indexterm" name="idm46444323706560"></a>

          <a class="indexterm" name="idm46444323705488"></a>

          <a class="link" href="functions.html#function_st-mpointfromwkb"><code class="literal">ST_MPointFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-mpointfromwkb"><code class="literal">ST_MultiPointFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">MultiPoint</code> value using its WKB
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-mpolyfromwkb"></a><p>
          <a class="indexterm" name="idm46444323693824"></a>

          <a class="indexterm" name="idm46444323692752"></a>

          <a class="link" href="functions.html#function_st-mpolyfromwkb"><code class="literal">ST_MPolyFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-mpolyfromwkb"><code class="literal">ST_MultiPolygonFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">MultiPolygon</code> value using its
          WKB representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
        </p></li><li class="listitem"><a name="function_st-pointfromwkb"></a><p>
          <a class="indexterm" name="idm46444323681152"></a>

          <a class="link" href="functions.html#function_st-pointfromwkb"><code class="literal">ST_PointFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">Point</code> value using its WKB
          representation and SRID.
        </p><p>
          <a class="link" href="functions.html#function_st-pointfromwkb"><code class="literal">ST_PointFromWKB()</code></a> handles its
          arguments as described in the introduction to this section.
        </p></li><li class="listitem"><a name="function_st-polyfromwkb"></a><p>
          <a class="indexterm" name="idm46444323670816"></a>

          <a class="indexterm" name="idm46444323669744"></a>

          <a class="link" href="functions.html#function_st-polyfromwkb"><code class="literal">ST_PolyFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>,
          <a class="link" href="functions.html#function_st-polyfromwkb"><code class="literal">ST_PolygonFromWKB(<em class="replaceable"><code>wkb</code></em>[,
          <em class="replaceable"><code>srid</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Constructs a <code class="literal">Polygon</code> value using its WKB
          representation and SRID.
        </p><p>
          These functions handle their arguments as described in the
          introduction to this section.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="gis-mysql-specific-functions"></a>12.16.5 MySQL-Specific Functions That Create Geometry Values</h3>

</div>

</div>

</div>
<p>
      MySQL provides a set of useful nonstandard functions for creating
      geometry values. The functions described in this section are MySQL
      extensions to the OpenGIS specification.
    </p><p>
      These functions produce geometry objects from either WKB values or
      geometry objects as arguments. If any argument is not a proper WKB
      or geometry representation of the proper object type, the return
      value is <code class="literal">NULL</code>.
    </p><p>
      For example, you can insert the geometry return value from
      <a class="link" href="functions.html#function_point"><code class="literal">Point()</code></a> directly into a
      <code class="literal">POINT</code> column:
</p><pre data-lang="sql" class="programlisting">INSERT INTO t1 (pt_col) VALUES(Point(1,2));</pre>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_geomcollection"></a><p>
          <a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection(<em class="replaceable"><code>g</code></em>
          [, <em class="replaceable"><code>g</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444323648320"></a><p>
          Constructs a <code class="literal">GeomCollection</code> value from the
          geometry arguments.
        </p><p>
          <a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a> returns all
          the proper geometries contained in the arguments even if a
          nonsupported geometry is present.
        </p><p>
          <a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a> with no
          arguments is permitted as a way to create an empty geometry.
          Also, functions such as
          <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code></a> that accept
          WKT geometry collection arguments understand both OpenGIS
          <code class="literal">'GEOMETRYCOLLECTION EMPTY'</code> standard syntax
          and MySQL <code class="literal">'GEOMETRYCOLLECTION()'</code>
          nonstandard syntax.
        </p><p>
          <a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a> and
          <a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection()</code></a> are
          synonymous, with
          <a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a> the preferred
          function.
        </p></li><li class="listitem"><a name="function_geometrycollection"></a><p>
          <a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection(<em class="replaceable"><code>g</code></em>
          [, <em class="replaceable"><code>g</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444323629696"></a><p>
          Constructs a <code class="literal">GeomCollection</code> value from the
          geometry arguments.
        </p><p>
          <a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection()</code></a> returns
          all the proper geometries contained in the arguments even if a
          nonsupported geometry is present.
        </p><p>
          <a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection()</code></a> with no
          arguments is permitted as a way to create an empty geometry.
          Also, functions such as
          <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code></a> that accept
          WKT geometry collection arguments understand both OpenGIS
          <code class="literal">'GEOMETRYCOLLECTION EMPTY'</code> standard syntax
          and MySQL <code class="literal">'GEOMETRYCOLLECTION()'</code>
          nonstandard syntax.
        </p><p>
          <a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a> and
          <a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection()</code></a> are
          synonymous, with
          <a class="link" href="functions.html#function_geomcollection"><code class="literal">GeomCollection()</code></a> the preferred
          function.
        </p></li><li class="listitem"><a name="function_linestring"></a><p>
          <a class="link" href="functions.html#function_linestring"><code class="literal">LineString(<em class="replaceable"><code>pt</code></em>
          [, <em class="replaceable"><code>pt</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444323611168"></a><p>
          Constructs a <code class="literal">LineString</code> value from a number
          of <code class="literal">Point</code> or WKB <code class="literal">Point</code>
          arguments. If the number of arguments is less than two, the
          return value is <code class="literal">NULL</code>.
        </p></li><li class="listitem"><a name="function_multilinestring"></a><p>
          <a class="link" href="functions.html#function_multilinestring"><code class="literal">MultiLineString(<em class="replaceable"><code>ls</code></em>
          [, <em class="replaceable"><code>ls</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444323600784"></a><p>
          Constructs a <code class="literal">MultiLineString</code> value using
          <code class="literal">LineString</code> or WKB
          <code class="literal">LineString</code> arguments.
        </p></li><li class="listitem"><a name="function_multipoint"></a><p>
          <a class="link" href="functions.html#function_multipoint"><code class="literal">MultiPoint(<em class="replaceable"><code>pt</code></em>
          [, <em class="replaceable"><code>pt2</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444323591280"></a><p>
          Constructs a <code class="literal">MultiPoint</code> value using
          <code class="literal">Point</code> or WKB <code class="literal">Point</code>
          arguments.
        </p></li><li class="listitem"><a name="function_multipolygon"></a><p>
          <a class="link" href="functions.html#function_multipolygon"><code class="literal">MultiPolygon(<em class="replaceable"><code>poly</code></em>
          [, <em class="replaceable"><code>poly</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444323581808"></a><p>
          Constructs a <code class="literal">MultiPolygon</code> value from a set
          of <code class="literal">Polygon</code> or WKB
          <code class="literal">Polygon</code> arguments.
        </p></li><li class="listitem"><a name="function_point"></a><p>
          <a class="link" href="functions.html#function_point"><code class="literal">Point(<em class="replaceable"><code>x</code></em>,
          <em class="replaceable"><code>y</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444323572368"></a><p>
          Constructs a <code class="literal">Point</code> using its coordinates.
        </p></li><li class="listitem"><a name="function_polygon"></a><p>
          <a class="link" href="functions.html#function_polygon"><code class="literal">Polygon(<em class="replaceable"><code>ls</code></em> [,
          <em class="replaceable"><code>ls</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444323564336"></a><p>
          Constructs a <code class="literal">Polygon</code> value from a number of
          <code class="literal">LineString</code> or WKB
          <code class="literal">LineString</code> arguments. If any argument does
          not represent a <code class="literal">LinearRing</code> (that is, not a
          closed and simple <code class="literal">LineString</code>), the return
          value is <code class="literal">NULL</code>.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="gis-format-conversion-functions"></a>12.16.6 Geometry Format Conversion Functions</h3>

</div>

</div>

</div>
<p>
      MySQL supports the functions listed in this section for converting
      geometry values from internal geometry format to WKT or WKB
      format, or for swapping the order of X and Y coordinates.
    </p><p>
      There are also functions to convert a string from WKT or WKB
      format to internal geometry format. See
      <a class="xref" href="functions.html#gis-wkt-functions" title="12.16.3 Functions That Create Geometry Values from WKT Values">Section 12.16.3, “Functions That Create Geometry Values from WKT Values”</a>, and
      <a class="xref" href="functions.html#gis-wkb-functions" title="12.16.4 Functions That Create Geometry Values from WKB Values">Section 12.16.4, “Functions That Create Geometry Values from WKB Values”</a>.
    </p><p>
      Functions such as <a class="link" href="functions.html#function_st-geomfromtext"><code class="literal">ST_GeomFromText()</code></a>
      that accept WKT geometry collection arguments understand both
      OpenGIS <code class="literal">'GEOMETRYCOLLECTION EMPTY'</code> standard
      syntax and MySQL <code class="literal">'GEOMETRYCOLLECTION()'</code>
      nonstandard syntax. Another way to produce an empty geometry
      collection is by calling
      <a class="link" href="functions.html#function_geometrycollection"><code class="literal">GeometryCollection()</code></a> with no
      arguments. Functions such as
      <a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsWKT()</code></a>
      that produce WKT values produce <code class="literal">'GEOMETRYCOLLECTION
      EMPTY'</code> standard syntax:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @s1 = ST_GeomFromText('GEOMETRYCOLLECTION()');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @s2 = ST_GeomFromText('GEOMETRYCOLLECTION EMPTY');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsWKT(@s1), ST_AsWKT(@s2);</code></strong>
+--------------------------+--------------------------+
| ST_AsWKT(@s1)            | ST_AsWKT(@s2)            |
+--------------------------+--------------------------+
| GEOMETRYCOLLECTION EMPTY | GEOMETRYCOLLECTION EMPTY |
+--------------------------+--------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsWKT(GeomCollection());</code></strong>
+----------------------------+
| ST_AsWKT(GeomCollection()) |
+----------------------------+
| GEOMETRYCOLLECTION EMPTY   |
+----------------------------+
</pre><p>
      Unless otherwise specified, functions in this section handle their
      arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If any argument is <code class="literal">NULL</code>, the return value
          is <code class="literal">NULL</code>.
        </p></li><li class="listitem"><p>
          If any geometry argument is not a syntactically well-formed
          geometry, an
          <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
          occurs.
        </p></li><li class="listitem"><p>
          If any geometry argument is in an undefined spatial reference
          system, the axes are output in the order they appear in the
          geometry and an
          <a class="link" href="error-handling.html#error_er_warn_srs_not_found_axis_order"><code class="literal">ER_WARN_SRS_NOT_FOUND_AXIS_ORDER</code></a>
          warning occurs.
        </p></li><li class="listitem"><p>
          By default, geographic coordinates (latitude, longitude) are
          interpreted as in the order specified by the spatial reference
          system of geometry arguments. An optional
          <em class="replaceable"><code>options</code></em> argument may be given to
          override the default axis order. <code class="option">options</code>
          consists of a list of comma-separated
          <code class="literal"><em class="replaceable"><code>key</code></em>=<em class="replaceable"><code>value</code></em></code>.
          The only permitted <em class="replaceable"><code>key</code></em> value is
          <code class="literal">axis-order</code>, with permitted values of
          <code class="literal">lat-long</code>, <code class="literal">long-lat</code> and
          <code class="literal">srid-defined</code> (the default).
        </p><p>
          If the <em class="replaceable"><code>options</code></em> argument is
          <code class="literal">NULL</code>, the return value is
          <code class="literal">NULL</code>. If the
          <em class="replaceable"><code>options</code></em> argument is invalid, an
          error occurs to indicate why.
        </p></li><li class="listitem"><p>
          Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
      These functions are available for format conversions or coordinate
      swapping:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-asbinary"></a><p>
          <a class="link" href="functions.html#function_st-asbinary"><code class="literal">ST_AsBinary(<em class="replaceable"><code>g</code></em>
          [, <em class="replaceable"><code>options</code></em>])</code></a>,
          <a class="link" href="functions.html#function_st-asbinary"><code class="literal">ST_AsWKB(<em class="replaceable"><code>g</code></em>
          [, <em class="replaceable"><code>options</code></em>])</code></a>
        </p><a class="indexterm" name="idm46444323514864"></a><p>
          Converts a value in internal geometry format to its WKB
          representation and returns the binary result.
        </p><p>
          The function return value has geographic coordinates
          (latitude, longitude) in the order specified by the spatial
          reference system that applies to the geometry argument. An
          optional <em class="replaceable"><code>options</code></em> argument may be
          given to override the default axis order.
        </p><p>
          <a class="link" href="functions.html#function_st-asbinary"><code class="literal">ST_AsBinary()</code></a> and
          <a class="link" href="functions.html#function_st-asbinary"><code class="literal">ST_AsWKB()</code></a>
          handle their arguments as described in the introduction to
          this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g = ST_LineFromText('LINESTRING(0 5,5 10,10 15)', 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeomFromWKB(ST_AsWKB(@g)));</code></strong>
+-----------------------------------------+
| ST_AsText(ST_GeomFromWKB(ST_AsWKB(@g))) |
+-----------------------------------------+
| LINESTRING(5 0,10 5,15 10)              |
+-----------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeomFromWKB(ST_AsWKB(@g, 'axis-order=long-lat')));</code></strong>
+----------------------------------------------------------------+
| ST_AsText(ST_GeomFromWKB(ST_AsWKB(@g, 'axis-order=long-lat'))) |
+----------------------------------------------------------------+
| LINESTRING(0 5,5 10,10 15)                                     |
+----------------------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeomFromWKB(ST_AsWKB(@g, 'axis-order=lat-long')));</code></strong>
+----------------------------------------------------------------+
| ST_AsText(ST_GeomFromWKB(ST_AsWKB(@g, 'axis-order=lat-long'))) |
+----------------------------------------------------------------+
| LINESTRING(5 0,10 5,15 10)                                     |
+----------------------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-astext"></a><p>
          <a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsText(<em class="replaceable"><code>g</code></em> [,
          <em class="replaceable"><code>options</code></em>])</code></a>,
          <a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsWKT(<em class="replaceable"><code>g</code></em>
          [, <em class="replaceable"><code>options</code></em>])</code></a>
        </p><a class="indexterm" name="idm46444323495408"></a><p>
          Converts a value in internal geometry format to its WKT
          representation and returns the string result.
        </p><p>
          The function return value has geographic coordinates
          (latitude, longitude) in the order specified by the spatial
          reference system that applies to the geometry argument. An
          optional <em class="replaceable"><code>options</code></em> argument may be
          given to override the default axis order.
        </p><p>
          <a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsText()</code></a> and
          <a class="link" href="functions.html#function_st-astext"><code class="literal">ST_AsWKT()</code></a>
          handle their arguments as described in the introduction to
          this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g = 'LineString(1 1,2 2,3 3)';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeomFromText(@g));</code></strong>
+--------------------------------+
| ST_AsText(ST_GeomFromText(@g)) |
+--------------------------------+
| LINESTRING(1 1,2 2,3 3)        |
+--------------------------------+
</pre><p>
          Output for <code class="literal">MultiPoint</code> values includes
          parentheses around each point. For example:
        </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeomFromText(@mp));</code></strong>
+---------------------------------+
| ST_AsText(ST_GeomFromText(@mp)) |
+---------------------------------+
| MULTIPOINT((1 1),(2 2),(3 3))   |
+---------------------------------+
</pre></li><li class="listitem"><a name="function_st-swapxy"></a><p>
          <a class="link" href="functions.html#function_st-swapxy"><code class="literal">ST_SwapXY(<em class="replaceable"><code>g</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444323478352"></a><p>
          Accepts an argument in internal geometry format, swaps the X
          and Y values of each coordinate pair within the geometry, and
          returns the result.
        </p><p>
          <a class="link" href="functions.html#function_st-swapxy"><code class="literal">ST_SwapXY()</code></a> handles its
          arguments as described in the introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g = ST_LineFromText('LINESTRING(0 5,5 10,10 15)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(@g);</code></strong>
+----------------------------+
| ST_AsText(@g)              |
+----------------------------+
| LINESTRING(0 5,5 10,10 15) |
+----------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_SwapXY(@g));</code></strong>
+----------------------------+
| ST_AsText(ST_SwapXY(@g))   |
+----------------------------+
| LINESTRING(5 0,10 5,15 10) |
+----------------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="gis-property-functions"></a>12.16.7 Geometry Property Functions</h3>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#gis-general-property-functions">12.16.7.1 General Geometry Property Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-point-property-functions">12.16.7.2 Point Property Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-linestring-property-functions">12.16.7.3 LineString and MultiLineString Property Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-polygon-property-functions">12.16.7.4 Polygon and MultiPolygon Property Functions</a></span></dt><dt><span class="section"><a href="functions.html#gis-geometrycollection-property-functions">12.16.7.5 GeometryCollection Property Functions</a></span></dt></dl>
</div>
<p>
      Each function that belongs to this group takes a geometry value as
      its argument and returns some quantitative or qualitative property
      of the geometry. Some functions restrict their argument type. Such
      functions return <code class="literal">NULL</code> if the argument is of an
      incorrect geometry type. For example, the
      <a class="link" href="functions.html#function_st-area"><code class="literal">ST_Area()</code></a> polygon function returns
      <code class="literal">NULL</code> if the object type is neither
      <code class="literal">Polygon</code> nor <code class="literal">MultiPolygon</code>.
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h4 class="title"><a name="gis-general-property-functions"></a>12.16.7.1 General Geometry Property Functions</h4>
</div>
</div>
</div>
<p>
        The functions listed in this section do not restrict their
        argument and accept a geometry value of any type.
      </p><p>
        Unless otherwise specified, functions in this section handle
        their arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If any argument is <code class="literal">NULL</code>, the return value
            is <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            If any geometry argument is not a syntactically well-formed
            geometry, an
            <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument has an SRID value that refers to an
            undefined spatial reference system (SRS), an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any SRID argument is not within the range of a 32-bit
            unsigned integer, an
            <a class="link" href="error-handling.html#error_er_data_out_of_range"><code class="literal">ER_DATA_OUT_OF_RANGE</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any SRID argument refers to an undefined SRS, an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        These functions are available for obtaining geometry properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-dimension"></a><p>
            <a class="link" href="functions.html#function_st-dimension"><code class="literal">ST_Dimension(<em class="replaceable"><code>g</code></em>)</code></a>
          </p><a class="indexterm" name="idm46444323441968"></a><p>
            Returns the inherent dimension of the geometry value
            <em class="replaceable"><code>g</code></em>. The dimension can be −1,
            0, 1, or 2. The meaning of these values is given in
            <a class="xref" href="data-types.html#gis-class-geometry" title="11.4.2.2 Geometry Class">Section 11.4.2.2, “Geometry Class”</a>.
          </p><p>
            <a class="link" href="functions.html#function_st-dimension"><code class="literal">ST_Dimension()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_Dimension(ST_GeomFromText('LineString(1 1,2 2)'));</code></strong>
+------------------------------------------------------+
| ST_Dimension(ST_GeomFromText('LineString(1 1,2 2)')) |
+------------------------------------------------------+
|                                                    1 |
+------------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-envelope"></a><p>
            <a class="link" href="functions.html#function_st-envelope"><code class="literal">ST_Envelope(<em class="replaceable"><code>g</code></em>)</code></a>
          </p><a class="indexterm" name="idm46444323429600"></a><p>
            Returns the minimum bounding rectangle (MBR) for the
            geometry value <em class="replaceable"><code>g</code></em>. The result is
            returned as a <code class="literal">Polygon</code> value that is
            defined by the corner points of the bounding box:
          </p><pre data-lang="sql" class="programlisting">POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,2 2)')));</code></strong>
+----------------------------------------------------------------+
| ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,2 2)'))) |
+----------------------------------------------------------------+
| POLYGON((1 1,2 1,2 2,1 2,1 1))                                 |
+----------------------------------------------------------------+
</pre><p>
            If the argument is a point or a vertical or horizontal line
            segment, <a class="link" href="functions.html#function_st-envelope"><code class="literal">ST_Envelope()</code></a>
            returns the point or the line segment as its MBR rather than
            returning an invalid polygon:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,1 2)')));</code></strong>
+----------------------------------------------------------------+
| ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,1 2)'))) |
+----------------------------------------------------------------+
| LINESTRING(1 1,1 2)                                            |
+----------------------------------------------------------------+
</pre><p>
            <a class="link" href="functions.html#function_st-envelope"><code class="literal">ST_Envelope()</code></a> handles its
            arguments as described in the introduction to this section,
            with this exception:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If the geometry has an SRID value for a geographic
                spatial reference system (SRS), an
                <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
                error occurs.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_st-geometrytype"></a><p>
            <a class="link" href="functions.html#function_st-geometrytype"><code class="literal">ST_GeometryType(<em class="replaceable"><code>g</code></em>)</code></a>
          </p><a class="indexterm" name="idm46444323409952"></a><p>
            Returns a binary string indicating the name of the geometry
            type of which the geometry instance
            <em class="replaceable"><code>g</code></em> is a member. The name
            corresponds to one of the instantiable
            <code class="literal">Geometry</code> subclasses.
          </p><p>
            <a class="link" href="functions.html#function_st-geometrytype"><code class="literal">ST_GeometryType()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_GeometryType(ST_GeomFromText('POINT(1 1)'));</code></strong>
+------------------------------------------------+
| ST_GeometryType(ST_GeomFromText('POINT(1 1)')) |
+------------------------------------------------+
| POINT                                          |
+------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-isempty"></a><p>
            <a class="link" href="functions.html#function_st-isempty"><code class="literal">ST_IsEmpty(<em class="replaceable"><code>g</code></em>)</code></a>
          </p><a class="indexterm" name="idm46444323397680"></a><p>
            This function is a placeholder that returns 1 for an empty
            geometry collection value or 0 otherwise.
          </p><p>
            The only valid empty geometry is represented in the form of
            an empty geometry collection value. MySQL does not support
            GIS <code class="literal">EMPTY</code> values such as <code class="literal">POINT
            EMPTY</code>.
          </p><p>
            <a class="link" href="functions.html#function_st-isempty"><code class="literal">ST_IsEmpty()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_st-issimple"></a><p>
            <a class="link" href="functions.html#function_st-issimple"><code class="literal">ST_IsSimple(<em class="replaceable"><code>g</code></em>)</code></a>
          </p><a class="indexterm" name="idm46444323387024"></a><p>
            Returns 1 if the geometry value <em class="replaceable"><code>g</code></em>
            is simple according to the ISO <em class="citetitle">SQL/MM Part 3:
            Spatial</em> standard.
            <a class="link" href="functions.html#function_st-issimple"><code class="literal">ST_IsSimple()</code></a> returns 0 if
            the argument is not simple.
          </p><p>
            The descriptions of the instantiable geometric classes given
            under <a class="xref" href="data-types.html#opengis-geometry-model" title="11.4.2 The OpenGIS Geometry Model">Section 11.4.2, “The OpenGIS Geometry Model”</a> include the
            specific conditions that cause class instances to be
            classified as not simple.
          </p><p>
            <a class="link" href="functions.html#function_st-issimple"><code class="literal">ST_IsSimple()</code></a> handles its
            arguments as described in the introduction to this section,
            with this exception:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If the geometry has a geographic SRS with a longitude or
                latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                    If any longitude argument is not in the range
                    (−180, 180], an
                    <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                    error occurs.
                  </p></li><li class="listitem"><p>
                    If any latitude argument is not in the range
                    [−90, 90], an
                    <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                    error occurs.
</p></li></ul>
</div>
<p>
                Ranges shown are in degrees. The exact range limits
                deviate slightly due to floating-point arithmetic.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_st-srid"></a><p>
            <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID(<em class="replaceable"><code>g</code></em>[,
            <em class="replaceable"><code>srid</code></em>])</code></a>
          </p><a class="indexterm" name="idm46444323367568"></a><p>
            With a single argument representing a valid geometry object
            <em class="replaceable"><code>g</code></em>,
            <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> returns an integer
            indicating the ID of the spatial reference system (SRS)
            associated with <em class="replaceable"><code>g</code></em>.
          </p><p>
            With the optional second argument representing a valid SRID
            value, <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> returns an
            object with the same type as its first argument with an SRID
            value equal to the second argument. This only sets the SRID
            value of the object; it does not perform any transformation
            of coordinate values.
          </p><p>
            <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> handles its
            arguments as described in the introduction to this section,
            with this exception:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                For the single-argument syntax,
                <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> returns the
                geometry SRID even if it refers to an undefined SRS. An
                <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
                does not occur.
</p></li></ul>
</div>
<p>
            <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID(<em class="replaceable"><code>g</code></em>,
            <em class="replaceable"><code>target_srid</code></em>)</code></a> and
            <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform(<em class="replaceable"><code>g</code></em>,
            <em class="replaceable"><code>target_srid</code></em>)</code></a> differ as
            follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> changes the
                geometry SRID value without transforming its
                coordinates.
              </p></li><li class="listitem"><p>
                <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform()</code></a> transforms
                the geometry coordinates in addition to changing its
                SRID value.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g = ST_GeomFromText('LineString(1 1,2 2)', 0);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_SRID(@g);</code></strong>
+-------------+
| ST_SRID(@g) |
+-------------+
|           0 |
+-------------+
mysql&gt; <strong class="userinput"><code>SET @g = ST_SRID(@g, 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_SRID(@g);</code></strong>
+-------------+
| ST_SRID(@g) |
+-------------+
|        4326 |
+-------------+
</pre><p>
            It is possible to create a geometry in a particular SRID by
            passing to <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> the
            result of one of the MySQL-specific functions for creating
            spatial values, along with an SRID value. For example:
          </p><pre data-lang="sql" class="programlisting">SET @g1 = ST_SRID(Point(1, 1), 4326);</pre><p>
            However, that method creates the geometry in SRID 0, then
            casts it to SRID 4326 (WGS 84). A preferable alternative is
            to create the geometry with the correct spatial reference
            system to begin with. For example:
          </p><pre data-lang="sql" class="programlisting">SET @g1 = ST_PointFromText('POINT(1 1)', 4326);
SET @g1 = ST_GeomFromText('POINT(1 1)', 4326);</pre><p>
            The two-argument form of
            <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> is useful for tasks
            such as correcting or changing the SRS of geometries that
            have an incorrect SRID.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a name="gis-point-property-functions"></a>12.16.7.2 Point Property Functions</h4>

</div>

</div>

</div>
<p>
        A <code class="literal">Point</code> consists of X and Y coordinates,
        which may be obtained using the
        <a class="link" href="functions.html#function_st-x"><code class="literal">ST_X()</code></a> and
        <a class="link" href="functions.html#function_st-y"><code class="literal">ST_Y()</code></a> functions, respectively.
        These functions also permit an optional second argument that
        specifies an X or Y coordinate value, in which case the function
        result is the <code class="literal">Point</code> object from the first
        argument with the appropriate coordinate modified to be equal to
        the second argument.
      </p><p>
        For <code class="literal">Point</code> objects that have a geographic
        spatial reference system (SRS), the longitude and latitude may
        be obtained using the
        <a class="link" href="functions.html#function_st-longitude"><code class="literal">ST_Longitude()</code></a> and
        <a class="link" href="functions.html#function_st-latitude"><code class="literal">ST_Latitude()</code></a> functions,
        respectively. These functions also permit an optional second
        argument that specifies a longitude or latitude value, in which
        case the function result is the <code class="literal">Point</code> object
        from the first argument with the longitude or latitude modified
        to be equal to the second argument.
      </p><p>
        Unless otherwise specified, functions in this section handle
        their arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If any argument is <code class="literal">NULL</code>, the return value
            is <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            If any geometry argument is a valid geometry but not a
            <code class="literal">Point</code> object, an
            <a class="link" href="error-handling.html#error_er_unexpected_geometry_type"><code class="literal">ER_UNEXPECTED_GEOMETRY_TYPE</code></a>
            error occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument is not a syntactically well-formed
            geometry, an
            <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument has an SRID value that refers to an
            undefined spatial reference system (SRS), an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If an X or Y coordinate argument is provided and the value
            is <code class="literal">-inf</code>, <code class="literal">+inf</code>, or
            <code class="literal">NaN</code>, an
            <a class="link" href="error-handling.html#error_er_data_out_of_range"><code class="literal">ER_DATA_OUT_OF_RANGE</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If a longitude or latitude argument is out of range, an
            error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If any longitude argument is not in the range
                (−180, 180], an
                <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If any latitude argument is not in the range [−90,
                90], an
                <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                error occurs.
</p></li></ul>
</div>
<p>
            Ranges shown are in degrees. The exact range limits deviate
            slightly due to floating-point arithmetic.
          </p></li><li class="listitem"><p>
            Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        These functions are available for obtaining point properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-latitude"></a><p>
            <a class="link" href="functions.html#function_st-latitude"><code class="literal">ST_Latitude(<em class="replaceable"><code>p</code></em>
            [, <em class="replaceable"><code>new_latitude_val</code></em>])</code></a>
          </p><a class="indexterm" name="idm46444323295344"></a><p>
            With a single argument representing a valid
            <code class="literal">Point</code> object <em class="replaceable"><code>p</code></em>
            that has a geographic spatial reference system (SRS),
            <a class="link" href="functions.html#function_st-latitude"><code class="literal">ST_Latitude()</code></a> returns the
            latitude value of <em class="replaceable"><code>p</code></em> as a
            double-precision number.
          </p><p>
            With the optional second argument representing a valid
            latitude value, <a class="link" href="functions.html#function_st-latitude"><code class="literal">ST_Latitude()</code></a>
            returns a <code class="literal">Point</code> object like the first
            argument with its latitude equal to the second argument.
          </p><p>
            <a class="link" href="functions.html#function_st-latitude"><code class="literal">ST_Latitude()</code></a> handles its
            arguments as described in the introduction to this section,
            with the addition that if the <code class="literal">Point</code>
            object is valid but does not have a geographic SRS, an
            <a class="link" href="error-handling.html#error_er_srs_not_geographic"><code class="literal">ER_SRS_NOT_GEOGRAPHIC</code></a> error
            occurs.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @pt = ST_GeomFromText('POINT(45 90)', 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Latitude(@pt);</code></strong>
+------------------+
| ST_Latitude(@pt) |
+------------------+
|               45 |
+------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Latitude(@pt, 10));</code></strong>
+---------------------------------+
| ST_AsText(ST_Latitude(@pt, 10)) |
+---------------------------------+
| POINT(10 90)                    |
+---------------------------------+
</pre><p>
            This function was added in MySQL 8.0.12.
          </p></li><li class="listitem"><a name="function_st-longitude"></a><p>
            <a class="link" href="functions.html#function_st-longitude"><code class="literal">ST_Longitude(<em class="replaceable"><code>p</code></em>
            [, <em class="replaceable"><code>new_longitude_val</code></em>])</code></a>
          </p><a class="indexterm" name="idm46444323273568"></a><p>
            With a single argument representing a valid
            <code class="literal">Point</code> object <em class="replaceable"><code>p</code></em>
            that has a geographic spatial reference system (SRS),
            <a class="link" href="functions.html#function_st-longitude"><code class="literal">ST_Longitude()</code></a> returns the
            longitude value of <em class="replaceable"><code>p</code></em> as a
            double-precision number.
          </p><p>
            With the optional second argument representing a valid
            longitude value,
            <a class="link" href="functions.html#function_st-longitude"><code class="literal">ST_Longitude()</code></a> returns a
            <code class="literal">Point</code> object like the first argument with
            its longitude equal to the second argument.
          </p><p>
            <a class="link" href="functions.html#function_st-longitude"><code class="literal">ST_Longitude()</code></a> handles its
            arguments as described in the introduction to this section,
            with the addition that if the <code class="literal">Point</code>
            object is valid but does not have a geographic SRS, an
            <a class="link" href="error-handling.html#error_er_srs_not_geographic"><code class="literal">ER_SRS_NOT_GEOGRAPHIC</code></a> error
            occurs.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @pt = ST_GeomFromText('POINT(45 90)', 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Longitude(@pt);</code></strong>
+-------------------+
| ST_Longitude(@pt) |
+-------------------+
|                90 |
+-------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Longitude(@pt, 10));</code></strong>
+----------------------------------+
| ST_AsText(ST_Longitude(@pt, 10)) |
+----------------------------------+
| POINT(45 10)                     |
+----------------------------------+
</pre><p>
            This function was added in MySQL 8.0.12.
          </p></li><li class="listitem"><a name="function_st-x"></a><p>
            <a class="link" href="functions.html#function_st-x"><code class="literal">ST_X(<em class="replaceable"><code>p</code></em>[,
            <em class="replaceable"><code>new_x_val</code></em>])</code></a>
          </p><a class="indexterm" name="idm46444323251904"></a><p>
            With a single argument representing a valid
            <code class="literal">Point</code> object
            <em class="replaceable"><code>p</code></em>,
            <a class="link" href="functions.html#function_st-x"><code class="literal">ST_X()</code></a> returns the
            X-coordinate value of <em class="replaceable"><code>p</code></em> as a
            double-precision number. As of MySQL 8.0.12, the X
            coordinate is considered to refer to the axis that appears
            first in the <code class="literal">Point</code> spatial reference
            system (SRS) definition.
          </p><p>
            With the optional second argument,
            <a class="link" href="functions.html#function_st-x"><code class="literal">ST_X()</code></a> returns a
            <code class="literal">Point</code> object like the first argument with
            its X coordinate equal to the second argument. As of MySQL
            8.0.12, if the <code class="literal">Point</code> object has a
            geographic SRS, the second argument must be in the proper
            range for longitude or latitude values.
          </p><p>
            <a class="link" href="functions.html#function_st-x"><code class="literal">ST_X()</code></a> handles its arguments
            as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_X(Point(56.7, 53.34));</code></strong>
+--------------------------+
| ST_X(Point(56.7, 53.34)) |
+--------------------------+
|                     56.7 |
+--------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_X(Point(56.7, 53.34), 10.5));</code></strong>
+-------------------------------------------+
| ST_AsText(ST_X(Point(56.7, 53.34), 10.5)) |
+-------------------------------------------+
| POINT(10.5 53.34)                         |
+-------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-y"></a><p>
            <a class="link" href="functions.html#function_st-y"><code class="literal">ST_Y(<em class="replaceable"><code>p</code></em>[,
            <em class="replaceable"><code>new_y_val</code></em>])</code></a>
          </p><a class="indexterm" name="idm46444323232336"></a><p>
            With a single argument representing a valid
            <code class="literal">Point</code> object
            <em class="replaceable"><code>p</code></em>,
            <a class="link" href="functions.html#function_st-y"><code class="literal">ST_Y()</code></a> returns the
            Y-coordinate value of <em class="replaceable"><code>p</code></em> as a
            double-precision number. As of MySQL 8.0.12, the Y
            coordinate is considered to refer to the axis that appears
            second in the <code class="literal">Point</code> spatial reference
            system (SRS) definition.
          </p><p>
            With the optional second argument,
            <a class="link" href="functions.html#function_st-y"><code class="literal">ST_Y()</code></a> returns a
            <code class="literal">Point</code> object like the first argument with
            its Y coordinate equal to the second argument. As of MySQL
            8.0.12, if the <code class="literal">Point</code> object has a
            geographic SRS, the second argument must be in the proper
            range for longitude or latitude values.
          </p><p>
            <a class="link" href="functions.html#function_st-y"><code class="literal">ST_Y()</code></a> handles its arguments
            as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_Y(Point(56.7, 53.34));</code></strong>
+--------------------------+
| ST_Y(Point(56.7, 53.34)) |
+--------------------------+
|                    53.34 |
+--------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Y(Point(56.7, 53.34), 10.5));</code></strong>
+-------------------------------------------+
| ST_AsText(ST_Y(Point(56.7, 53.34), 10.5)) |
+-------------------------------------------+
| POINT(56.7 10.5)                          |
+-------------------------------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a name="gis-linestring-property-functions"></a>12.16.7.3 LineString and MultiLineString Property Functions</h4>

</div>

</div>

</div>
<p>
        A <code class="literal">LineString</code> consists of
        <code class="literal">Point</code> values. You can extract particular
        points of a <code class="literal">LineString</code>, count the number of
        points that it contains, or obtain its length.
      </p><p>
        Some functions in this section also work for
        <code class="literal">MultiLineString</code> values.
      </p><p>
        Unless otherwise specified, functions in this section handle
        their arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If any argument is <code class="literal">NULL</code> or any geometry
            argument is an empty geometry, the return value is
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            If any geometry argument is not a syntactically well-formed
            geometry, an
            <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument has an SRID value that refers to an
            undefined spatial reference system (SRS), an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        These functions are available for obtaining linestring
        properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-endpoint"></a><p>
            <a class="indexterm" name="idm46444323198864"></a>

            <a class="link" href="functions.html#function_st-endpoint"><code class="literal">ST_EndPoint(<em class="replaceable"><code>ls</code></em>)</code></a>
          </p><p>
            Returns the <code class="literal">Point</code> that is the endpoint of
            the <code class="literal">LineString</code> value
            <em class="replaceable"><code>ls</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-endpoint"><code class="literal">ST_EndPoint()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls = 'LineString(1 1,2 2,3 3)';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_EndPoint(ST_GeomFromText(@ls)));</code></strong>
+----------------------------------------------+
| ST_AsText(ST_EndPoint(ST_GeomFromText(@ls))) |
+----------------------------------------------+
| POINT(3 3)                                   |
+----------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-isclosed"></a><p>
            <a class="indexterm" name="idm46444323185264"></a>

            <a class="link" href="functions.html#function_st-isclosed"><code class="literal">ST_IsClosed(<em class="replaceable"><code>ls</code></em>)</code></a>
          </p><p>
            For a <code class="literal">LineString</code> value
            <em class="replaceable"><code>ls</code></em>,
            <a class="link" href="functions.html#function_st-isclosed"><code class="literal">ST_IsClosed()</code></a> returns 1 if
            <em class="replaceable"><code>ls</code></em> is closed (that is, its
            <a class="link" href="functions.html#function_st-startpoint"><code class="literal">ST_StartPoint()</code></a> and
            <a class="link" href="functions.html#function_st-endpoint"><code class="literal">ST_EndPoint()</code></a> values are the
            same).
          </p><p>
            For a <code class="literal">MultiLineString</code> value
            <em class="replaceable"><code>ls</code></em>,
            <a class="link" href="functions.html#function_st-isclosed"><code class="literal">ST_IsClosed()</code></a> returns 1 if
            <em class="replaceable"><code>ls</code></em> is closed (that is, the
            <a class="link" href="functions.html#function_st-startpoint"><code class="literal">ST_StartPoint()</code></a> and
            <a class="link" href="functions.html#function_st-endpoint"><code class="literal">ST_EndPoint()</code></a> values are the
            same for each <code class="literal">LineString</code> in
            <em class="replaceable"><code>ls</code></em>).
          </p><p>
            <a class="link" href="functions.html#function_st-isclosed"><code class="literal">ST_IsClosed()</code></a> returns 0 if
            <em class="replaceable"><code>ls</code></em> is not closed, and
            <code class="literal">NULL</code> if <em class="replaceable"><code>ls</code></em> is
            <code class="literal">NULL</code>.
          </p><p>
            <a class="link" href="functions.html#function_st-isclosed"><code class="literal">ST_IsClosed()</code></a> handles its
            arguments as described in the introduction to this section,
            with this exception:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If the geometry has an SRID value for a geographic
                spatial reference system (SRS), an
                <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
                error occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls1 = 'LineString(1 1,2 2,3 3,2 2)';</code></strong>
mysql&gt; <strong class="userinput"><code>SET @ls2 = 'LineString(1 1,2 2,3 3,1 1)';</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT ST_IsClosed(ST_GeomFromText(@ls1));</code></strong>
+------------------------------------+
| ST_IsClosed(ST_GeomFromText(@ls1)) |
+------------------------------------+
|                                  0 |
+------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT ST_IsClosed(ST_GeomFromText(@ls2));</code></strong>
+------------------------------------+
| ST_IsClosed(ST_GeomFromText(@ls2)) |
+------------------------------------+
|                                  1 |
+------------------------------------+

mysql&gt; <strong class="userinput"><code>SET @ls3 = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT ST_IsClosed(ST_GeomFromText(@ls3));</code></strong>
+------------------------------------+
| ST_IsClosed(ST_GeomFromText(@ls3)) |
+------------------------------------+
|                                  0 |
+------------------------------------+
</pre></li><li class="listitem"><a name="function_st-length"></a><p>
            <a class="indexterm" name="idm46444323151824"></a>

            <a class="link" href="functions.html#function_st-length"><code class="literal">ST_Length(<em class="replaceable"><code>ls</code></em>
            [, <em class="replaceable"><code>unit</code></em>])</code></a>
          </p><p>
            Returns a double-precision number indicating the length of
            the <code class="literal">LineString</code> or
            <code class="literal">MultiLineString</code> value
            <em class="replaceable"><code>ls</code></em> in its associated spatial
            reference system. The length of a
            <code class="literal">MultiLineString</code> value is equal to the sum
            of the lengths of its elements.
          </p><p>
            <a class="link" href="functions.html#function_st-length"><code class="literal">ST_Length()</code></a> computes a result
            as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If the geometry is a valid <code class="literal">LineString</code>
                in a Cartesian SRS, the return value is the Cartesian
                length of the geometry.
              </p></li><li class="listitem"><p>
                If the geometry is a valid
                <code class="literal">MultiLineString</code> in a Cartesian SRS,
                the return value is the sum of the Cartesian lengths of
                its elements.
              </p></li><li class="listitem"><p>
                If the geometry is a valid <code class="literal">LineString</code>
                in a geographic SRS, the return value is the geodetic
                length of the geometry in that SRS, in meters.
              </p></li><li class="listitem"><p>
                If the geometry is a valid
                <code class="literal">MultiLineString</code> in a geographic SRS,
                the return value is the sum of the geodetic lengths of
                its elements in that SRS, in meters.
</p></li></ul>
</div>
<p>
            <a class="link" href="functions.html#function_st-length"><code class="literal">ST_Length()</code></a> handles its
            arguments as described in the introduction to this section,
            with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If the geometry is not a <code class="literal">LineString</code>
                or <code class="literal">MultiLineString</code>, the return value
                is <code class="literal">NULL</code>.
              </p></li><li class="listitem"><p>
                If the geometry is geometrically invalid, either the
                result is an undefined length (that is, it can be any
                number), or an error occurs.
              </p></li><li class="listitem"><p>
                If the length computation result is
                <code class="literal">+inf</code>, an
                <a class="link" href="error-handling.html#error_er_data_out_of_range"><code class="literal">ER_DATA_OUT_OF_RANGE</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If the geometry has a geographic SRS with a longitude or
                latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                    If any longitude argument is not in the range
                    (−180, 180], an
                    <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                    error occurs.
                  </p></li><li class="listitem"><p>
                    If any latitude argument is not in the range
                    [−90, 90], an
                    <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                    error occurs.
</p></li></ul>
</div>
<p>
                Ranges shown are in degrees. The exact range limits
                deviate slightly due to floating-point arithmetic.
</p></li></ul>
</div>
<p>
            As of MySQL 8.0.16,
            <a class="link" href="functions.html#function_st-length"><code class="literal">ST_Length()</code></a> permits an
            optional <em class="replaceable"><code>unit</code></em> argument that
            specifies the linear unit for the returned length value.
            These rules apply:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If a unit is specified but not supported by MySQL, an
                <a class="link" href="error-handling.html#error_er_unit_not_found"><code class="literal">ER_UNIT_NOT_FOUND</code></a> error
                occurs.
              </p></li><li class="listitem"><p>
                If a supported linear unit is specified and the SRID is
                0, an
                <a class="link" href="error-handling.html#error_er_geometry_in_unknown_length_unit"><code class="literal">ER_GEOMETRY_IN_UNKNOWN_LENGTH_UNIT</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If a supported linear unit is specified and the SRID is
                not 0, the result is in that unit.
              </p></li><li class="listitem"><p>
                If a unit is not specified, the result is in the unit of
                the SRS of the geometries, whether Cartesian or
                geographic. Currently, all MySQL SRSs are expressed in
                meters.
</p></li></ul>
</div>
<p>
            A unit is supported if it is found in the
            <code class="literal">INFORMATION_SCHEMA</code>
            <a class="link" href="information-schema.html#st-units-of-measure-table" title="25.35 The INFORMATION_SCHEMA ST_UNITS_OF_MEASURE Table"><code class="literal">ST_UNITS_OF_MEASURE</code></a> table. See
            <a class="xref" href="information-schema.html#st-units-of-measure-table" title="25.35 The INFORMATION_SCHEMA ST_UNITS_OF_MEASURE Table">Section 25.35, “The INFORMATION_SCHEMA ST_UNITS_OF_MEASURE Table”</a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls = ST_GeomFromText('LineString(1 1,2 2,3 3)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Length(@ls);</code></strong>
+--------------------+
| ST_Length(@ls)     |
+--------------------+
| 2.8284271247461903 |
+--------------------+

mysql&gt; <strong class="userinput"><code>SET @mls = ST_GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Length(@mls);</code></strong>
+-------------------+
| ST_Length(@mls)   |
+-------------------+
| 4.242640687119286 |
+-------------------+

mysql&gt; <strong class="userinput"><code>SET @ls = ST_GeomFromText('LineString(1 1,2 2,3 3)', 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Length(@ls);</code></strong>
+-------------------+
| ST_Length(@ls)    |
+-------------------+
| 313701.9623204328 |
+-------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_Length(@ls, 'metre');</code></strong>
+-------------------------+
| ST_Length(@ls, 'metre') |
+-------------------------+
|       313701.9623204328 |
+-------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_Length(@ls, 'foot');</code></strong>
+------------------------+
| ST_Length(@ls, 'foot') |
+------------------------+
|     1029205.9131247795 |
+------------------------+
</pre></li><li class="listitem"><a name="function_st-numpoints"></a><p>
            <a class="indexterm" name="idm46444323096384"></a>

            <a class="link" href="functions.html#function_st-numpoints"><code class="literal">ST_NumPoints(<em class="replaceable"><code>ls</code></em>)</code></a>
          </p><p>
            Returns the number of <code class="literal">Point</code> objects in
            the <code class="literal">LineString</code> value
            <em class="replaceable"><code>ls</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-numpoints"><code class="literal">ST_NumPoints()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls = 'LineString(1 1,2 2,3 3)';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_NumPoints(ST_GeomFromText(@ls));</code></strong>
+------------------------------------+
| ST_NumPoints(ST_GeomFromText(@ls)) |
+------------------------------------+
|                                  3 |
+------------------------------------+
</pre></li><li class="listitem"><a name="function_st-pointn"></a><p>
            <a class="indexterm" name="idm46444323082848"></a>

            <a class="link" href="functions.html#function_st-pointn"><code class="literal">ST_PointN(<em class="replaceable"><code>ls</code></em>,
            <em class="replaceable"><code>N</code></em>)</code></a>
          </p><p>
            Returns the <em class="replaceable"><code>N</code></em>-th
            <code class="literal">Point</code> in the
            <code class="literal">Linestring</code> value
            <em class="replaceable"><code>ls</code></em>. Points are numbered beginning
            with 1.
          </p><p>
            <a class="link" href="functions.html#function_st-pointn"><code class="literal">ST_PointN()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls = 'LineString(1 1,2 2,3 3)';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_PointN(ST_GeomFromText(@ls),2));</code></strong>
+----------------------------------------------+
| ST_AsText(ST_PointN(ST_GeomFromText(@ls),2)) |
+----------------------------------------------+
| POINT(2 2)                                   |
+----------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-startpoint"></a><p>
            <a class="indexterm" name="idm46444323068400"></a>

            <a class="link" href="functions.html#function_st-startpoint"><code class="literal">ST_StartPoint(<em class="replaceable"><code>ls</code></em>)</code></a>
          </p><p>
            Returns the <code class="literal">Point</code> that is the start point
            of the <code class="literal">LineString</code> value
            <em class="replaceable"><code>ls</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-startpoint"><code class="literal">ST_StartPoint()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls = 'LineString(1 1,2 2,3 3)';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_StartPoint(ST_GeomFromText(@ls)));</code></strong>
+------------------------------------------------+
| ST_AsText(ST_StartPoint(ST_GeomFromText(@ls))) |
+------------------------------------------------+
| POINT(1 1)                                     |
+------------------------------------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a name="gis-polygon-property-functions"></a>12.16.7.4 Polygon and MultiPolygon Property Functions</h4>

</div>

</div>

</div>
<p>
        Functions in this section return properties of
        <code class="literal">Polygon</code> or <code class="literal">MultiPolygon</code>
        values.
      </p><p>
        Unless otherwise specified, functions in this section handle
        their arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If any argument is <code class="literal">NULL</code> or any geometry
            argument is an empty geometry, the return value is
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            If any geometry argument is not a syntactically well-formed
            geometry, an
            <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument has an SRID value that refers to an
            undefined spatial reference system (SRS), an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            For functions that take multiple geometry arguments, if
            those arguments do not have the same SRID, an
            <a class="link" href="error-handling.html#error_er_gis_different_srids"><code class="literal">ER_GIS_DIFFERENT_SRIDS</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        These functions are available for obtaining polygon properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-area"></a><p>
            <a class="indexterm" name="idm46444323038560"></a>

            <a class="link" href="functions.html#function_st-area"><code class="literal">ST_Area({<em class="replaceable"><code>poly</code></em>|<em class="replaceable"><code>mpoly</code></em>})</code></a>
          </p><p>
            Returns a double-precision number indicating the area of the
            <code class="literal">Polygon</code> or
            <code class="literal">MultiPolygon</code> argument, as measured in its
            spatial reference system.
          </p><p>
            As of MySQL 8.0.13, <a class="link" href="functions.html#function_st-area"><code class="literal">ST_Area()</code></a>
            handles its arguments as described in the introduction to
            this section, with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If the geometry is geometrically invalid, either the
                result is an undefined area (that is, it can be any
                number), or an error occurs.
              </p></li><li class="listitem"><p>
                If the geometry is valid but is not a
                <code class="literal">Polygon</code> or
                <code class="literal">MultiPolygon</code> object, an
                <a class="link" href="error-handling.html#error_er_unexpected_geometry_type"><code class="literal">ER_UNEXPECTED_GEOMETRY_TYPE</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If the geometry is a valid <code class="literal">Polygon</code> in
                a Cartesian SRS, the result is the Cartesian area of the
                polygon.
              </p></li><li class="listitem"><p>
                If the geometry is a valid
                <code class="literal">MultiPolygon</code> in a Cartesian SRS, the
                result is the sum of the Cartesian area of the polygons.
              </p></li><li class="listitem"><p>
                If the geometry is a valid <code class="literal">Polygon</code> in
                a geographic SRS, the result is the geodetic area of the
                polygon in that SRS, in square meters.
              </p></li><li class="listitem"><p>
                If the geometry is a valid
                <code class="literal">MultiPolygon</code> in a geographic SRS, the
                result is the sum of geodetic area of the polygons in
                that SRS, in square meters.
              </p></li><li class="listitem"><p>
                If an area computation results in
                <code class="literal">+inf</code>, an
                <a class="link" href="error-handling.html#error_er_data_out_of_range"><code class="literal">ER_DATA_OUT_OF_RANGE</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If the geometry has a geographic SRS with a longitude or
                latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                    If any longitude argument is not in the range
                    (−180, 180], an
                    <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                    error occurs.
                  </p></li><li class="listitem"><p>
                    If any latitude argument is not in the range
                    [−90, 90], an
                    <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                    error occurs.
</p></li></ul>
</div>
<p>
                Ranges shown are in degrees. The exact range limits
                deviate slightly due to floating-point arithmetic.
</p></li></ul>
</div>
<p>
            Prior to MySQL 8.0.13,
            <a class="link" href="functions.html#function_st-area"><code class="literal">ST_Area()</code></a> handles its
            arguments as described in the introduction to this section,
            with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                For arguments of dimension 0 or 1, the result is 0.
              </p></li><li class="listitem"><p>
                If a geometry is empty, the return value is 0 rather
                than <code class="literal">NULL</code>.
              </p></li><li class="listitem"><p>
                For a geometry collection, the result is the sum of the
                area values of all components. If the geometry
                collection is empty, its area is returned as 0.
              </p></li><li class="listitem"><p>
                If the geometry has an SRID value for a geographic
                spatial reference system (SRS), an
                <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
                error occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @poly =</code></strong>
       <strong class="userinput"><code>'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Area(ST_GeomFromText(@poly));</code></strong>
+---------------------------------+
| ST_Area(ST_GeomFromText(@poly)) |
+---------------------------------+
|                               4 |
+---------------------------------+

mysql&gt; <strong class="userinput"><code>SET @mpoly =</code></strong>
       <strong class="userinput"><code>'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Area(ST_GeomFromText(@mpoly));</code></strong>
+----------------------------------+
| ST_Area(ST_GeomFromText(@mpoly)) |
+----------------------------------+
|                                8 |
+----------------------------------+
</pre></li><li class="listitem"><a name="function_st-centroid"></a><p>
            <a class="indexterm" name="idm46444322991984"></a>

            <a class="link" href="functions.html#function_st-centroid"><code class="literal">ST_Centroid({<em class="replaceable"><code>poly</code></em>|<em class="replaceable"><code>mpoly</code></em>})</code></a>
          </p><p>
            Returns the mathematical centroid for the
            <code class="literal">Polygon</code> or
            <code class="literal">MultiPolygon</code> argument as a
            <code class="literal">Point</code>. The result is not guaranteed to be
            on the <code class="literal">MultiPolygon</code>.
          </p><p>
            This function processes geometry collections by computing
            the centroid point for components of highest dimension in
            the collection. Such components are extracted and made into
            a single <code class="literal">MultiPolygon</code>,
            <code class="literal">MultiLineString</code>, or
            <code class="literal">MultiPoint</code> for centroid computation.
          </p><p>
            <a class="link" href="functions.html#function_st-centroid"><code class="literal">ST_Centroid()</code></a> handles its
            arguments as described in the introduction to this section,
            with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                The return value is <code class="literal">NULL</code> for the
                additional condition that the argument is an empty
                geometry collection.
              </p></li><li class="listitem"><p>
                If the geometry has an SRID value for a geographic
                spatial reference system (SRS), an
                <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
                error occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @poly =</code></strong>
       <strong class="userinput"><code>ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_GeometryType(@poly),ST_AsText(ST_Centroid(@poly));</code></strong>
+------------------------+--------------------------------------------+
| ST_GeometryType(@poly) | ST_AsText(ST_Centroid(@poly))              |
+------------------------+--------------------------------------------+
| POLYGON                | POINT(4.958333333333333 4.958333333333333) |
+------------------------+--------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-exteriorring"></a><p>
            <a class="indexterm" name="idm46444322968272"></a>

            <a class="link" href="functions.html#function_st-exteriorring"><code class="literal">ST_ExteriorRing(<em class="replaceable"><code>poly</code></em>)</code></a>
          </p><p>
            Returns the exterior ring of the <code class="literal">Polygon</code>
            value <em class="replaceable"><code>poly</code></em> as a
            <code class="literal">LineString</code>.
          </p><p>
            <a class="link" href="functions.html#function_st-exteriorring"><code class="literal">ST_ExteriorRing()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @poly =</code></strong>
       <strong class="userinput"><code>'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_ExteriorRing(ST_GeomFromText(@poly)));</code></strong>
+----------------------------------------------------+
| ST_AsText(ST_ExteriorRing(ST_GeomFromText(@poly))) |
+----------------------------------------------------+
| LINESTRING(0 0,0 3,3 3,3 0,0 0)                    |
+----------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-interiorringn"></a><p>
            <a class="indexterm" name="idm46444322953712"></a>

            <a class="link" href="functions.html#function_st-interiorringn"><code class="literal">ST_InteriorRingN(<em class="replaceable"><code>poly</code></em>,
            <em class="replaceable"><code>N</code></em>)</code></a>
          </p><p>
            Returns the <em class="replaceable"><code>N</code></em>-th interior ring
            for the <code class="literal">Polygon</code> value
            <em class="replaceable"><code>poly</code></em> as a
            <code class="literal">LineString</code>. Rings are numbered beginning
            with 1.
          </p><p>
            <a class="link" href="functions.html#function_st-interiorringn"><code class="literal">ST_InteriorRingN()</code></a> handles
            its arguments as described in the introduction to this
            section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @poly =</code></strong>
       <strong class="userinput"><code>'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_InteriorRingN(ST_GeomFromText(@poly),1));</code></strong>
+-------------------------------------------------------+
| ST_AsText(ST_InteriorRingN(ST_GeomFromText(@poly),1)) |
+-------------------------------------------------------+
| LINESTRING(1 1,1 2,2 2,2 1,1 1)                       |
+-------------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-numinteriorrings"></a><p>
            <a class="indexterm" name="idm46444322938272"></a>

            <a class="indexterm" name="idm46444322937200"></a>

            <a class="link" href="functions.html#function_st-numinteriorrings"><code class="literal">ST_NumInteriorRing(<em class="replaceable"><code>poly</code></em>)</code></a>,
            <a class="link" href="functions.html#function_st-numinteriorrings"><code class="literal">ST_NumInteriorRings(<em class="replaceable"><code>poly</code></em>)</code></a>
          </p><p>
            Returns the number of interior rings in the
            <code class="literal">Polygon</code> value
            <em class="replaceable"><code>poly</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-numinteriorrings"><code class="literal">ST_NumInteriorRing()</code></a>
            and <a class="link" href="functions.html#function_st-numinteriorrings"><code class="literal">ST_NuminteriorRings()</code></a>
            handle their arguments as described in the introduction to
            this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @poly =</code></strong>
       <strong class="userinput"><code>'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_NumInteriorRings(ST_GeomFromText(@poly));</code></strong>
+---------------------------------------------+
| ST_NumInteriorRings(ST_GeomFromText(@poly)) |
+---------------------------------------------+
|                                           1 |
+---------------------------------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a name="gis-geometrycollection-property-functions"></a>12.16.7.5 GeometryCollection Property Functions</h4>

</div>

</div>

</div>
<p>
        These functions return properties of
        <code class="literal">GeometryCollection</code> values.
      </p><p>
        Unless otherwise specified, functions in this section handle
        their arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If any argument is <code class="literal">NULL</code> or any geometry
            argument is an empty geometry, the return value is
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            If any geometry argument is not a syntactically well-formed
            geometry, an
            <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument has an SRID value that refers to an
            undefined spatial reference system (SRS), an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        These functions are available for obtaining geometry collection
        properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-geometryn"></a><p>
            <a class="indexterm" name="idm46444322907264"></a>

            <a class="link" href="functions.html#function_st-geometryn"><code class="literal">ST_GeometryN(<em class="replaceable"><code>gc</code></em>,
            <em class="replaceable"><code>N</code></em>)</code></a>
          </p><p>
            Returns the <em class="replaceable"><code>N</code></em>-th geometry in the
            <code class="literal">GeometryCollection</code> value
            <em class="replaceable"><code>gc</code></em>. Geometries are numbered
            beginning with 1.
          </p><p>
            <a class="link" href="functions.html#function_st-geometryn"><code class="literal">ST_GeometryN()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeometryN(ST_GeomFromText(@gc),1));</code></strong>
+-------------------------------------------------+
| ST_AsText(ST_GeometryN(ST_GeomFromText(@gc),1)) |
+-------------------------------------------------+
| POINT(1 1)                                      |
+-------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-numgeometries"></a><p>
            <a class="indexterm" name="idm46444322893376"></a>

            <a class="link" href="functions.html#function_st-numgeometries"><code class="literal">ST_NumGeometries(<em class="replaceable"><code>gc</code></em>)</code></a>
          </p><p>
            Returns the number of geometries in the
            <code class="literal">GeometryCollection</code> value
            <em class="replaceable"><code>gc</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-numgeometries"><code class="literal">ST_NumGeometries()</code></a> handles
            its arguments as described in the introduction to this
            section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_NumGeometries(ST_GeomFromText(@gc));</code></strong>
+----------------------------------------+
| ST_NumGeometries(ST_GeomFromText(@gc)) |
+----------------------------------------+
|                                      2 |
+----------------------------------------+
</pre></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="spatial-operator-functions"></a>12.16.8 Spatial Operator Functions</h3>

</div>

</div>

</div>
<p>
      OpenGIS proposes a number of functions that can produce
      geometries. They are designed to implement spatial operators.
    </p><p>
      These functions support all argument type combinations except
      those that are inapplicable according to the
      <a class="ulink" href="http://www.opengeospatial.org" target="_top">Open Geospatial
      Consortium</a> specification.
    </p><p>
      Unless otherwise specified, functions in this section handle their
      arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If any argument is <code class="literal">NULL</code>, the return value
          is <code class="literal">NULL</code>.
        </p></li><li class="listitem"><p>
          If any geometry argument is not a syntactically well-formed
          geometry, an
          <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
          occurs.
        </p></li><li class="listitem"><p>
          If any geometry argument has an SRID value that refers to an
          undefined spatial reference system (SRS), an
          <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error occurs.
        </p></li><li class="listitem"><p>
          For functions that take multiple geometry arguments, if those
          arguments do not have the same SRID, an
          <a class="link" href="error-handling.html#error_er_gis_different_srids"><code class="literal">ER_GIS_DIFFERENT_SRIDS</code></a> error
          occurs.
        </p></li><li class="listitem"><p>
          If any geometry argument has an SRID value for a geographic
          SRS, an
          <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
          error occurs.
        </p></li><li class="listitem"><p>
          Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
      These spatial operator functions are available:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-buffer"></a><p>
          <a class="indexterm" name="idm46444322862880"></a>

          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer(<em class="replaceable"><code>g</code></em>,
          <em class="replaceable"><code>d</code></em>[,
          <em class="replaceable"><code>strategy1</code></em>[,
          <em class="replaceable"><code>strategy2</code></em>[,
          <em class="replaceable"><code>strategy3</code></em>]]])</code></a>
        </p><p>
          Returns a geometry that represents all points whose distance
          from the geometry value <em class="replaceable"><code>g</code></em> is less
          than or equal to a distance of <em class="replaceable"><code>d</code></em>.
        </p><p>
          If the geometry argument is empty,
          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a> returns an empty
          geometry.
        </p><p>
          If the distance is 0,
          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a> returns the
          geometry argument unchanged:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @pt = ST_GeomFromText('POINT(0 0)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Buffer(@pt, 0));</code></strong>
+------------------------------+
| ST_AsText(ST_Buffer(@pt, 0)) |
+------------------------------+
| POINT(0 0)                   |
+------------------------------+
</pre><p>
          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a> supports negative
          distances for <code class="literal">Polygon</code> and
          <code class="literal">MultiPolygon</code> values, and for geometry
          collections containing <code class="literal">Polygon</code> or
          <code class="literal">MultiPolygon</code> values. The result may be an
          empty geometry.
        </p><p>
          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a> permits up to three
          optional strategy arguments following the distance argument.
          Strategies influence buffer computation. These arguments are
          byte string values produced by the
          <a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy()</code></a> function,
          to be used for point, join, and end strategies:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Point strategies apply to <code class="literal">Point</code> and
              <code class="literal">MultiPoint</code> geometries. If no point
              strategy is specified, the default is
              <a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy('point_circle',
              32)</code></a>.
            </p></li><li class="listitem"><p>
              Join strategies apply to <code class="literal">LineString</code>,
              <code class="literal">MultiLineString</code>,
              <code class="literal">Polygon</code>, and
              <code class="literal">MultiPolygon</code> geometries. If no join
              strategy is specified, the default is
              <a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy('join_round',
              32)</code></a>.
            </p></li><li class="listitem"><p>
              End strategies apply to <code class="literal">LineString</code> and
              <code class="literal">MultiLineString</code> geometries. If no end
              strategy is specified, the default is
              <a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy('end_round',
              32)</code></a>.
</p></li></ul>
</div>
<p>
          Up to one strategy of each type may be specified, and they may
          be given in any order.
        </p><p>
          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a> handles its
          arguments as described in the introduction to this section,
          with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              For a negative distance for <code class="literal">Point</code>,
              <code class="literal">MultiPoint</code>,
              <code class="literal">LineString</code>, and
              <code class="literal">MultiLineString</code> values, and for
              geometry collections not containing any
              <code class="literal">Polygon</code> or
              <code class="literal">MultiPolygon</code> values, an
              <a class="link" href="error-handling.html#error_er_wrong_arguments"><code class="literal">ER_WRONG_ARGUMENTS</code></a> error
              occurs.
            </p></li><li class="listitem"><p>
              If multiple strategies of a given type are specified, an
              <a class="link" href="error-handling.html#error_er_wrong_arguments"><code class="literal">ER_WRONG_ARGUMENTS</code></a> error
              occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @pt = ST_GeomFromText('POINT(0 0)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @pt_strategy = ST_Buffer_Strategy('point_square');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Buffer(@pt, 2, @pt_strategy));</code></strong>
+--------------------------------------------+
| ST_AsText(ST_Buffer(@pt, 2, @pt_strategy)) |
+--------------------------------------------+
| POLYGON((-2 -2,2 -2,2 2,-2 2,-2 -2))       |
+--------------------------------------------+
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls = ST_GeomFromText('LINESTRING(0 0,0 5,5 5)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @end_strategy = ST_Buffer_Strategy('end_flat');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @join_strategy = ST_Buffer_Strategy('join_round', 10);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Buffer(@ls, 5, @end_strategy, @join_strategy))</code></strong>
+---------------------------------------------------------------+
| ST_AsText(ST_Buffer(@ls, 5, @end_strategy, @join_strategy))   |
+---------------------------------------------------------------+
| POLYGON((5 5,5 10,0 10,-3.5355339059327373 8.535533905932738, |
| -5 5,-5 0,0 0,5 0,5 5))                                       |
+---------------------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-buffer-strategy"></a><p>
          <a class="indexterm" name="idm46444322805856"></a>

          <a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy(<em class="replaceable"><code>strategy</code></em>[,
          <em class="replaceable"><code>points_per_circle</code></em>])</code></a>
        </p><p>
          This function returns a strategy byte string for use with
          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a> to influence buffer
          computation.
        </p><p>
          Information about strategies is available at
          <a class="ulink" href="http://www.boost.org" target="_top">Boost.org</a>.
        </p><p>
          The first argument must be a string indicating a strategy
          option:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              For point strategies, permitted values are
              <code class="literal">'point_circle'</code> and
              <code class="literal">'point_square'</code>.
            </p></li><li class="listitem"><p>
              For join strategies, permitted values are
              <code class="literal">'join_round'</code> and
              <code class="literal">'join_miter'</code>.
            </p></li><li class="listitem"><p>
              For end strategies, permitted values are
              <code class="literal">'end_round'</code> and
              <code class="literal">'end_flat'</code>.
</p></li></ul>
</div>
<p>
          If the first argument is <code class="literal">'point_circle'</code>,
          <code class="literal">'join_round'</code>,
          <code class="literal">'join_miter'</code>, or
          <code class="literal">'end_round'</code>, the
          <em class="replaceable"><code>points_per_circle</code></em> argument must be
          given as a positive numeric value. The maximum
          <em class="replaceable"><code>points_per_circle</code></em> value is the
          value of the
          <a class="link" href="server-administration.html#sysvar_max_points_in_geometry"><code class="literal">max_points_in_geometry</code></a> system
          variable.
        </p><p>
          For examples, see the description of
          <a class="link" href="functions.html#function_st-buffer"><code class="literal">ST_Buffer()</code></a>.
        </p><p>
          <a class="link" href="functions.html#function_st-buffer-strategy"><code class="literal">ST_Buffer_Strategy()</code></a> handles
          its arguments as described in the introduction to this
          section, with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If any argument is invalid, an
              <a class="link" href="error-handling.html#error_er_wrong_arguments"><code class="literal">ER_WRONG_ARGUMENTS</code></a> error
              occurs.
            </p></li><li class="listitem"><p>
              If the first argument is <code class="literal">'point_square'</code>
              or <code class="literal">'end_flat'</code>, the
              <em class="replaceable"><code>points_per_circle</code></em> argument must
              not be given or an
              <a class="link" href="error-handling.html#error_er_wrong_arguments"><code class="literal">ER_WRONG_ARGUMENTS</code></a> error
              occurs.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_st-convexhull"></a><p>
          <a class="indexterm" name="idm46444322772608"></a>

          <a class="link" href="functions.html#function_st-convexhull"><code class="literal">ST_ConvexHull(<em class="replaceable"><code>g</code></em>)</code></a>
        </p><p>
          Returns a geometry that represents the convex hull of the
          geometry value <em class="replaceable"><code>g</code></em>.
        </p><p>
          This function computes a geometry's convex hull by first
          checking whether its vertex points are colinear. The function
          returns a linear hull if so, a polygon hull otherwise. This
          function processes geometry collections by extracting all
          vertex points of all components of the collection, creating a
          <code class="literal">MultiPoint</code> value from them, and computing
          its convex hull.
        </p><p>
          <a class="link" href="functions.html#function_st-convexhull"><code class="literal">ST_ConvexHull()</code></a> handles its
          arguments as described in the introduction to this section,
          with this exception:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The return value is <code class="literal">NULL</code> for the
              additional condition that the argument is an empty
              geometry collection.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g = 'MULTIPOINT(5 0,25 0,15 10,15 25)';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_ConvexHull(ST_GeomFromText(@g)));</code></strong>
+-----------------------------------------------+
| ST_AsText(ST_ConvexHull(ST_GeomFromText(@g))) |
+-----------------------------------------------+
| POLYGON((5 0,25 0,15 25,5 0))                 |
+-----------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-difference"></a><p>
          <a class="indexterm" name="idm46444322756256"></a>

          <a class="link" href="functions.html#function_st-difference"><code class="literal">ST_Difference(<em class="replaceable"><code>g1</code></em>,
          <em class="replaceable"><code>g2</code></em>)</code></a>
        </p><p>
          Returns a geometry that represents the point set difference of
          the geometry values <em class="replaceable"><code>g1</code></em> and
          <em class="replaceable"><code>g2</code></em>.
        </p><p>
          <a class="link" href="functions.html#function_st-difference"><code class="literal">ST_Difference()</code></a> handles its
          arguments as described in the introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = Point(1,1), @g2 = Point(2,2);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Difference(@g1, @g2));</code></strong>
+------------------------------------+
| ST_AsText(ST_Difference(@g1, @g2)) |
+------------------------------------+
| POINT(1 1)                         |
+------------------------------------+
</pre></li><li class="listitem"><a name="function_st-intersection"></a><p>
          <a class="indexterm" name="idm46444322742608"></a>

          <a class="link" href="functions.html#function_st-intersection"><code class="literal">ST_Intersection(<em class="replaceable"><code>g1</code></em>,
          <em class="replaceable"><code>g2</code></em>)</code></a>
        </p><p>
          Returns a geometry that represents the point set intersection
          of the geometry values <em class="replaceable"><code>g1</code></em> and
          <em class="replaceable"><code>g2</code></em>.
        </p><p>
          <a class="link" href="functions.html#function_st-intersection"><code class="literal">ST_Intersection()</code></a> handles its
          arguments as described in the introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = ST_GeomFromText('LineString(1 1, 3 3)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @g2 = ST_GeomFromText('LineString(1 3, 3 1)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Intersection(@g1, @g2));</code></strong>
+--------------------------------------+
| ST_AsText(ST_Intersection(@g1, @g2)) |
+--------------------------------------+
| POINT(2 2)                           |
+--------------------------------------+
</pre></li><li class="listitem"><a name="function_st-symdifference"></a><p>
          <a class="indexterm" name="idm46444322728208"></a>

          <a class="link" href="functions.html#function_st-symdifference"><code class="literal">ST_SymDifference(<em class="replaceable"><code>g1</code></em>,
          <em class="replaceable"><code>g2</code></em>)</code></a>
        </p><p>
          Returns a geometry that represents the point set symmetric
          difference of the geometry values
          <em class="replaceable"><code>g1</code></em> and
          <em class="replaceable"><code>g2</code></em>, which is defined as:
        </p><pre data-lang="clike" class="programlisting"><em class="replaceable"><code>g1</code></em> symdifference <em class="replaceable"><code>g2</code></em> := (<em class="replaceable"><code>g1</code></em> union <em class="replaceable"><code>g2</code></em>) difference (<em class="replaceable"><code>g1</code></em> intersection <em class="replaceable"><code>g2</code></em>)
</pre><p>
          Or, in function call notation:
        </p><pre data-lang="clike" class="programlisting">ST_SymDifference(<em class="replaceable"><code>g1</code></em>, <em class="replaceable"><code>g2</code></em>) = ST_Difference(ST_Union(<em class="replaceable"><code>g1</code></em>, <em class="replaceable"><code>g2</code></em>), ST_Intersection(<em class="replaceable"><code>g1</code></em>, <em class="replaceable"><code>g2</code></em>))
</pre><p>
          <a class="link" href="functions.html#function_st-symdifference"><code class="literal">ST_SymDifference()</code></a> handles its
          arguments as described in the introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = Point(1,1), @g2 = Point(2,2);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_SymDifference(@g1, @g2));</code></strong>
+---------------------------------------+
| ST_AsText(ST_SymDifference(@g1, @g2)) |
+---------------------------------------+
| MULTIPOINT((1 1),(2 2))               |
+---------------------------------------+
</pre></li><li class="listitem"><a name="function_st-transform"></a><p>
          <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform(<em class="replaceable"><code>g</code></em>,
          <em class="replaceable"><code>target_srid</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444322705360"></a><p>
          Transforms a geometry from one spatial reference system (SRS)
          to another. The return value is a geometry of the same type as
          the input geometry with all coordinates transformed to the
          target SRID, <em class="replaceable"><code>target_srid</code></em>.
          Transformation support is limited to geographic SRSs, unless
          the SRID of the geometry argument is the same as the target
          SRID value, in which case the return value is the input
          geometry for any valid SRS.
        </p><p>
          <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform()</code></a> handles its
          arguments as described in the introduction to this section,
          with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Geometry arguments that have an SRID value for a
              geographic SRS do not produce an error.
            </p></li><li class="listitem"><p>
              If the geometry or target SRID argument has an SRID value
              that refers to an undefined spatial reference system
              (SRS), an <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If the geometry is in an SRS that
              <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform()</code></a> cannot
              transform from, an
              <a class="link" href="error-handling.html#error_er_transform_source_srs_not_supported"><code class="literal">ER_TRANSFORM_SOURCE_SRS_NOT_SUPPORTED</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If the target SRID is in an SRS that
              <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform()</code></a> cannot
              transform to, an
              <a class="link" href="error-handling.html#error_er_transform_target_srs_not_supported"><code class="literal">ER_TRANSFORM_TARGET_SRS_NOT_SUPPORTED</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If the geometry is in an SRS that is not WGS 84 and has no
              TOWGS84 clause, an
              <a class="link" href="error-handling.html#error_er_transform_source_srs_missing_towgs84"><code class="literal">ER_TRANSFORM_SOURCE_SRS_MISSING_TOWGS84</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If the target SRID is in an SRS that is not WGS 84 and has
              no TOWGS84 clause, an
              <a class="link" href="error-handling.html#error_er_transform_target_srs_missing_towgs84"><code class="literal">ER_TRANSFORM_TARGET_SRS_MISSING_TOWGS84</code></a>
              error occurs.
</p></li></ul>
</div>
<p>
          <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID(<em class="replaceable"><code>g</code></em>,
          <em class="replaceable"><code>target_srid</code></em>)</code></a> and
          <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform(<em class="replaceable"><code>g</code></em>,
          <em class="replaceable"><code>target_srid</code></em>)</code></a> differ as
          follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <a class="link" href="functions.html#function_st-srid"><code class="literal">ST_SRID()</code></a> changes the
              geometry SRID value without transforming its coordinates.
            </p></li><li class="listitem"><p>
              <a class="link" href="functions.html#function_st-transform"><code class="literal">ST_Transform()</code></a> transforms
              the geometry coordinates in addition to changing its SRID
              value.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @p = ST_GeomFromText('POINT(52.381389 13.064444)', 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(@p);</code></strong>
+----------------------------+
| ST_AsText(@p)              |
+----------------------------+
| POINT(52.381389 13.064444) |
+----------------------------+
mysql&gt; <strong class="userinput"><code>SET @p = ST_Transform(@p, 4230);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(@p);</code></strong>
+---------------------------------------------+
| ST_AsText(@p)                               |
+---------------------------------------------+
| POINT(52.38208611407426 13.065520672345304) |
+---------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-union"></a><p>
          <a class="indexterm" name="idm46444322667424"></a>

          <a class="link" href="functions.html#function_st-union"><code class="literal">ST_Union(<em class="replaceable"><code>g1</code></em>,
          <em class="replaceable"><code>g2</code></em>)</code></a>
        </p><p>
          Returns a geometry that represents the point set union of the
          geometry values <em class="replaceable"><code>g1</code></em> and
          <em class="replaceable"><code>g2</code></em>.
        </p><p>
          <a class="link" href="functions.html#function_st-union"><code class="literal">ST_Union()</code></a> handles its
          arguments as described in the introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = ST_GeomFromText('LineString(1 1, 3 3)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @g2 = ST_GeomFromText('LineString(1 3, 3 1)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Union(@g1, @g2));</code></strong>
+--------------------------------------+
| ST_AsText(ST_Union(@g1, @g2))        |
+--------------------------------------+
| MULTILINESTRING((1 1,3 3),(1 3,3 1)) |
+--------------------------------------+
</pre></li></ul>
</div>
<p>
      In addition, <a class="xref" href="functions.html#gis-property-functions" title="12.16.7 Geometry Property Functions">Section 12.16.7, “Geometry Property Functions”</a>, discusses
      several functions that construct new geometries from existing
      ones. See that section for descriptions of these functions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          <a class="link" href="functions.html#function_st-envelope"><code class="literal">ST_Envelope(<em class="replaceable"><code>g</code></em>)</code></a>
        </p></li><li class="listitem"><p>
          <a class="link" href="functions.html#function_st-startpoint"><code class="literal">ST_StartPoint(<em class="replaceable"><code>ls</code></em>)</code></a>
        </p></li><li class="listitem"><p>
          <a class="link" href="functions.html#function_st-endpoint"><code class="literal">ST_EndPoint(<em class="replaceable"><code>ls</code></em>)</code></a>
        </p></li><li class="listitem"><p>
          <a class="link" href="functions.html#function_st-pointn"><code class="literal">ST_PointN(<em class="replaceable"><code>ls</code></em>,
          <em class="replaceable"><code>N</code></em>)</code></a>
        </p></li><li class="listitem"><p>
          <a class="link" href="functions.html#function_st-exteriorring"><code class="literal">ST_ExteriorRing(<em class="replaceable"><code>poly</code></em>)</code></a>
        </p></li><li class="listitem"><p>
          <a class="link" href="functions.html#function_st-interiorringn"><code class="literal">ST_InteriorRingN(<em class="replaceable"><code>poly</code></em>,
          <em class="replaceable"><code>N</code></em>)</code></a>
        </p></li><li class="listitem"><p>
          <a class="link" href="functions.html#function_st-geometryn"><code class="literal">ST_GeometryN(<em class="replaceable"><code>gc</code></em>,
          <em class="replaceable"><code>N</code></em>)</code></a>
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="spatial-relation-functions"></a>12.16.9 Functions That Test Spatial Relations Between Geometry Objects</h3>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#spatial-relation-functions-object-shapes">12.16.9.1 Spatial Relation Functions That Use Object Shapes</a></span></dt><dt><span class="section"><a href="functions.html#spatial-relation-functions-mbr">12.16.9.2 Spatial Relation Functions That Use Minimum Bounding Rectangles</a></span></dt></dl>
</div>
<p>
      The functions described in this section take two geometries as
      arguments and return a qualitative or quantitative relation
      between them.
    </p><p>
      MySQL implements two sets of functions using function names
      defined by the OpenGIS specification. One set tests the
      relationship between two geometry values using precise object
      shapes, the other set uses object minimum bounding rectangles
      (MBRs).
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h4 class="title"><a name="spatial-relation-functions-object-shapes"></a>12.16.9.1 Spatial Relation Functions That Use Object Shapes</h4>
</div>
</div>
</div>
<p>
        The OpenGIS specification defines the following functions to
        test the relationship between two geometry values
        <code class="literal">g1</code> and <code class="literal">g2</code>, using precise
        object shapes. The return values 1 and 0 indicate true and
        false, respectively, except for
        <a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a>, which returns
        distance values.
      </p><p>
        Functions in this section detect arguments in either Cartesian
        or geographic spatial reference systems (SRSs), and return
        results appropriate to the SRS.
      </p><p>
        Unless otherwise specified, functions in this section handle
        their arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If any argument is <code class="literal">NULL</code> or any geometry
            argument is an empty geometry, the return value is
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            If any geometry argument is not a syntactically well-formed
            geometry, an
            <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument refers to an undefined spatial
            reference system (SRS), an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            For functions that take multiple geometry arguments, if
            those arguments do not have the same SRID, an
            <a class="link" href="error-handling.html#error_er_gis_different_srids"><code class="literal">ER_GIS_DIFFERENT_SRIDS</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument is geometrically invalid, either
            the result is true or false (it is undefined which), or an
            error occurs.
          </p></li><li class="listitem"><p>
            For geographic SRS geometry arguments, if any argument has a
            longitude or latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If a longitude value is not in the range (−180,
                180], an
                <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If a latitude value is not in the range [−90, 90],
                an
                <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                error occurs.
</p></li></ul>
</div>
<p>
            Ranges shown are in degrees. If an SRS uses another unit,
            the range uses the corresponding values in its unit. The
            exact range limits deviate slightly due to floating-point
            arithmetic.
          </p></li><li class="listitem"><p>
            Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        These object-shape functions are available for testing geometry
        relationships:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-contains"></a><p>
            <a class="indexterm" name="idm46444322605312"></a>

            <a class="link" href="functions.html#function_st-contains"><code class="literal">ST_Contains(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> completely contains
            <em class="replaceable"><code>g2</code></em>. This tests the opposite
            relationship as <a class="link" href="functions.html#function_st-within"><code class="literal">ST_Within()</code></a>.
          </p><p>
            <a class="link" href="functions.html#function_st-contains"><code class="literal">ST_Contains()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_st-crosses"></a><p>
            <a class="indexterm" name="idm46444322594208"></a>

            <a class="link" href="functions.html#function_st-crosses"><code class="literal">ST_Crosses(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Two geometries <span class="emphasis"><em>spatially cross</em></span> if their
            spatial relation has the following properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Unless <code class="literal">g1</code> and <code class="literal">g2</code>
                are both of dimension 1: <code class="literal">g1</code> crosses
                <code class="literal">g2</code> if the interior of
                <code class="literal">g2</code> has points in common with the
                interior of <code class="literal">g1</code>, but
                <code class="literal">g2</code> does not cover the entire interior
                of <code class="literal">g1</code>.
              </p></li><li class="listitem"><p>
                If both <code class="literal">g1</code> and <code class="literal">g2</code>
                are of dimension 1: If the lines cross each other in a
                finite number of points (that is, no common line
                segments, only single points in common).
</p></li></ul>
</div>
<p>
            This function returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> spatially crosses
            <em class="replaceable"><code>g2</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-crosses"><code class="literal">ST_Crosses()</code></a> handles its
            arguments as described in the introduction to this section
            except that the return value is <code class="literal">NULL</code> for
            these additional conditions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                <code class="literal">g1</code> is of dimension 2
                (<code class="literal">Polygon</code> or
                <code class="literal">MultiPolygon</code>).
              </p></li><li class="listitem"><p>
                <em class="replaceable"><code>g2</code></em> is of dimension 1
                (<code class="literal">Point</code> or
                <code class="literal">MultiPoint</code>).
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_st-disjoint"></a><p>
            <a class="indexterm" name="idm46444322567504"></a>

            <a class="link" href="functions.html#function_st-disjoint"><code class="literal">ST_Disjoint(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> is spatially disjoint from
            (does not intersect) <em class="replaceable"><code>g2</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-disjoint"><code class="literal">ST_Disjoint()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_st-distance"></a><p>
            <a class="indexterm" name="idm46444322557632"></a>

            <a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em> [,
            <em class="replaceable"><code>unit</code></em>])</code></a>
          </p><p>
            Returns the distance between <em class="replaceable"><code>g1</code></em>
            and <em class="replaceable"><code>g2</code></em>, measured in the length
            unit of the spatial reference system (SRS) of the geometry
            arguments, or in the unit of the optional
            <em class="replaceable"><code>unit</code></em> argument if that is
            specified.
          </p><p>
            This function processes geometry collections by returning
            the shortest distance among all combinations of the
            components of the two geometry arguments.
          </p><p>
            <a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a> handles its
            geometry arguments as described in the introduction to this
            section, with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                <a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a> detects
                arguments in a geographic (ellipsoidal) spatial
                reference system and returns the geodetic distance on
                the ellipsoid. As of MySQL 8.0.18,
                <a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a> supports
                distance calculations for geographic SRS arguments of
                all geometry types. Prior to MySQL 8.0.18, the only
                permitted geographic argument types are
                <code class="literal">Point</code> and <code class="literal">Point</code>,
                or <code class="literal">Point</code> and
                <code class="literal">MultiPoint</code> (in any argument order).
                If called with other geometry type argument combinations
                in a geographic SRS, an
                <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If any argument is geometrically invalid, either the
                result is an undefined distance (that is, it can be any
                number), or an error occurs.
              </p></li><li class="listitem"><p>
                If an intermediate or final result produces
                <code class="literal">NaN</code> or a negative number, an
                <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a>
                error occurs.
</p></li></ul>
</div>
<p>
            As of MySQL 8.0.14,
            <a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a> permits an
            optional <em class="replaceable"><code>unit</code></em> argument that
            specifies the linear unit for the returned distance value.
            These rules apply:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If a unit is specified but not supported by MySQL, an
                <a class="link" href="error-handling.html#error_er_unit_not_found"><code class="literal">ER_UNIT_NOT_FOUND</code></a> error
                occurs.
              </p></li><li class="listitem"><p>
                If a supported linear unit is specified and the SRID is
                0, an
                <a class="link" href="error-handling.html#error_er_geometry_in_unknown_length_unit"><code class="literal">ER_GEOMETRY_IN_UNKNOWN_LENGTH_UNIT</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If a supported linear unit is specified and the SRID is
                not 0, the result is in that unit.
              </p></li><li class="listitem"><p>
                If a unit is not specified, the result is in the unit of
                the SRS of the geometries, whether Cartesian or
                geographic. Currently, all MySQL SRSs are expressed in
                meters.
</p></li></ul>
</div>
<p>
            A unit is supported if it is found in the
            <code class="literal">INFORMATION_SCHEMA</code>
            <a class="link" href="information-schema.html#st-units-of-measure-table" title="25.35 The INFORMATION_SCHEMA ST_UNITS_OF_MEASURE Table"><code class="literal">ST_UNITS_OF_MEASURE</code></a> table. See
            <a class="xref" href="information-schema.html#st-units-of-measure-table" title="25.35 The INFORMATION_SCHEMA ST_UNITS_OF_MEASURE Table">Section 25.35, “The INFORMATION_SCHEMA ST_UNITS_OF_MEASURE Table”</a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = Point(1,1);</code></strong>
mysql&gt; <strong class="userinput"><code>SET @g2 = Point(2,2);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Distance(@g1, @g2);</code></strong>
+-----------------------+
| ST_Distance(@g1, @g2) |
+-----------------------+
|    1.4142135623730951 |
+-----------------------+

mysql&gt; <strong class="userinput"><code>SET @g1 = ST_GeomFromText('POINT(1 1)', 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SET @g2 = ST_GeomFromText('POINT(2 2)', 4326);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Distance(@g1, @g2);</code></strong>
+-----------------------+
| ST_Distance(@g1, @g2) |
+-----------------------+
|     156874.3859490455 |
+-----------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_Distance(@g1, @g2, 'metre');</code></strong>
+--------------------------------+
| ST_Distance(@g1, @g2, 'metre') |
+--------------------------------+
|              156874.3859490455 |
+--------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_Distance(@g1, @g2, 'foot');</code></strong>
+-------------------------------+
| ST_Distance(@g1, @g2, 'foot') |
+-------------------------------+
|             514679.7439273146 |
+-------------------------------+
</pre><p>
            For the special case of distance calculations on a sphere,
            see the <a class="link" href="functions.html#function_st-distance-sphere"><code class="literal">ST_Distance_Sphere()</code></a>
            function.
          </p></li><li class="listitem"><a name="function_st-equals"></a><p>
            <a class="indexterm" name="idm46444322511152"></a>

            <a class="link" href="functions.html#function_st-equals"><code class="literal">ST_Equals(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> is spatially equal to
            <em class="replaceable"><code>g2</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-equals"><code class="literal">ST_Equals()</code></a> handles its
            arguments as described in the introduction to this section,
            except that it does not return <code class="literal">NULL</code> for
            empty geometry arguments.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = Point(1,1), @g2 = Point(2,2);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Equals(@g1, @g1), ST_Equals(@g1, @g2);</code></strong>
+---------------------+---------------------+
| ST_Equals(@g1, @g1) | ST_Equals(@g1, @g2) |
+---------------------+---------------------+
|                   1 |                   0 |
+---------------------+---------------------+
</pre></li><li class="listitem"><a name="function_st-intersects"></a><p>
            <a class="indexterm" name="idm46444322496848"></a>

            <a class="link" href="functions.html#function_st-intersects"><code class="literal">ST_Intersects(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> spatially intersects
            <em class="replaceable"><code>g2</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-intersects"><code class="literal">ST_Intersects()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_st-overlaps"></a><p>
            <a class="indexterm" name="idm46444322487072"></a>

            <a class="link" href="functions.html#function_st-overlaps"><code class="literal">ST_Overlaps(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Two geometries <span class="emphasis"><em>spatially overlap</em></span> if
            they intersect and their intersection results in a geometry
            of the same dimension but not equal to either of the given
            geometries.
          </p><p>
            This function returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> spatially overlaps
            <em class="replaceable"><code>g2</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-overlaps"><code class="literal">ST_Overlaps()</code></a> handles its
            arguments as described in the introduction to this section
            except that the return value is <code class="literal">NULL</code> for
            the additional condition that the dimensions of the two
            geometries are not equal.
          </p></li><li class="listitem"><a name="function_st-touches"></a><p>
            <a class="indexterm" name="idm46444322475312"></a>

            <a class="link" href="functions.html#function_st-touches"><code class="literal">ST_Touches(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Two geometries <span class="emphasis"><em>spatially touch</em></span> if their
            interiors do not intersect, but the boundary of one of the
            geometries intersects either the boundary or the interior of
            the other.
          </p><p>
            This function returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> spatially touches
            <em class="replaceable"><code>g2</code></em>.
          </p><p>
            <a class="link" href="functions.html#function_st-touches"><code class="literal">ST_Touches()</code></a> handles its
            arguments as described in the introduction to this section
            except that the return value is <code class="literal">NULL</code> for
            the additional condition that both geometries are of
            dimension 0 (<code class="literal">Point</code> or
            <code class="literal">MultiPoint</code>).
          </p></li><li class="listitem"><a name="function_st-within"></a><p>
            <a class="indexterm" name="idm46444322462128"></a>

            <a class="link" href="functions.html#function_st-within"><code class="literal">ST_Within(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether
            <em class="replaceable"><code>g1</code></em> is spatially within
            <em class="replaceable"><code>g2</code></em>. This tests the opposite
            relationship as
            <a class="link" href="functions.html#function_st-contains"><code class="literal">ST_Contains()</code></a>.
          </p><p>
            <a class="link" href="functions.html#function_st-within"><code class="literal">ST_Within()</code></a> handles its
            arguments as described in the introduction to this section.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a name="spatial-relation-functions-mbr"></a>12.16.9.2 Spatial Relation Functions That Use Minimum Bounding Rectangles</h4>

</div>

</div>

</div>
<a class="indexterm" name="idm46444322452496"></a><a class="indexterm" name="idm46444322451456"></a><p>
        MySQL provides several MySQL-specific functions that test the
        relationship between minimum bounding rectangles (MBRs) of two
        geometries <code class="literal">g1</code> and <code class="literal">g2</code>. The
        return values 1 and 0 indicate true and false, respectively.
      </p><p>
        The bounding box of a point is interpreted as a point that is
        both boundary and interior.
      </p><p>
        The bounding box of a straight horizontal or vertical line is
        interpreted as a line where the interior of the line is also
        boundary. The endpoints are boundary points.
      </p><p>
        If any of the parameters are geometry collections, the interior,
        boundary, and exterior of those parameters are those of the
        union of all elements in the collection.
      </p><p>
        Functions in this section detect arguments in either Cartesian
        or geographic spatial reference systems (SRSs), and return
        results appropriate to the SRS.
      </p><p>
        Unless otherwise specified, functions in this section handle
        their arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            If any argument is <code class="literal">NULL</code> or an empty
            geometry, the return value is <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            If any geometry argument is not a syntactically well-formed
            geometry, an
            <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any geometry argument refers to an undefined spatial
            reference system (SRS), an
            <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            For functions that take multiple geometry arguments, if
            those arguments do not have the same SRID, an
            <a class="link" href="error-handling.html#error_er_gis_different_srids"><code class="literal">ER_GIS_DIFFERENT_SRIDS</code></a> error
            occurs.
          </p></li><li class="listitem"><p>
            If any argument is geometrically invalid, either the result
            is true or false (it is undefined which), or an error
            occurs.
          </p></li><li class="listitem"><p>
            For geographic SRS geometry arguments, if any argument has a
            longitude or latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                If a longitude value is not in the range (−180,
                180], an
                <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                error occurs.
              </p></li><li class="listitem"><p>
                If a latitude value is not in the range [−90, 90],
                an
                <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                error occurs.
</p></li></ul>
</div>
<p>
            Ranges shown are in degrees. If an SRS uses another unit,
            the range uses the corresponding values in its unit. The
            exact range limits deviate slightly due to floating-point
            arithmetic.
          </p></li><li class="listitem"><p>
            Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        These MBR functions are available for testing geometry
        relationships:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_mbrcontains"></a><p>
            <a class="indexterm" name="idm46444322422752"></a>

            <a class="link" href="functions.html#function_mbrcontains"><code class="literal">MBRContains(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether the minimum bounding
            rectangle of <em class="replaceable"><code>g1</code></em> contains the
            minimum bounding rectangle of <em class="replaceable"><code>g2</code></em>.
            This tests the opposite relationship as
            <a class="link" href="functions.html#function_mbrwithin"><code class="literal">MBRWithin()</code></a>.
          </p><p>
            <a class="link" href="functions.html#function_mbrcontains"><code class="literal">MBRContains()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @g2 = ST_GeomFromText('Point(1 1)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT MBRContains(@g1,@g2), MBRWithin(@g2,@g1);</code></strong>
+----------------------+--------------------+
| MBRContains(@g1,@g2) | MBRWithin(@g2,@g1) |
+----------------------+--------------------+
|                    1 |                  1 |
+----------------------+--------------------+
</pre></li><li class="listitem"><a name="function_mbrcoveredby"></a><p>
            <a class="indexterm" name="idm46444322408336"></a>

            <a class="link" href="functions.html#function_mbrcoveredby"><code class="literal">MBRCoveredBy(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether the minimum bounding
            rectangle of <em class="replaceable"><code>g1</code></em> is covered by the
            minimum bounding rectangle of <em class="replaceable"><code>g2</code></em>.
            This tests the opposite relationship as
            <a class="link" href="functions.html#function_mbrcovers"><code class="literal">MBRCovers()</code></a>.
          </p><p>
            <a class="link" href="functions.html#function_mbrcoveredby"><code class="literal">MBRCoveredBy()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @g2 = ST_GeomFromText('Point(1 1)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT MBRCovers(@g1,@g2), MBRCoveredby(@g1,@g2);</code></strong>
+--------------------+-----------------------+
| MBRCovers(@g1,@g2) | MBRCoveredby(@g1,@g2) |
+--------------------+-----------------------+
|                  1 |                     0 |
+--------------------+-----------------------+
mysql&gt; <strong class="userinput"><code>SELECT MBRCovers(@g2,@g1), MBRCoveredby(@g2,@g1);</code></strong>
+--------------------+-----------------------+
| MBRCovers(@g2,@g1) | MBRCoveredby(@g2,@g1) |
+--------------------+-----------------------+
|                  0 |                     1 |
+--------------------+-----------------------+
</pre></li><li class="listitem"><a name="function_mbrcovers"></a><p>
            <a class="indexterm" name="idm46444322392688"></a>

            <a class="link" href="functions.html#function_mbrcovers"><code class="literal">MBRCovers(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether the minimum bounding
            rectangle of <em class="replaceable"><code>g1</code></em> covers the
            minimum bounding rectangle of <em class="replaceable"><code>g2</code></em>.
            This tests the opposite relationship as
            <a class="link" href="functions.html#function_mbrcoveredby"><code class="literal">MBRCoveredBy()</code></a>. See the
            description of <a class="link" href="functions.html#function_mbrcoveredby"><code class="literal">MBRCoveredBy()</code></a>
            for examples.
          </p><p>
            <a class="link" href="functions.html#function_mbrcovers"><code class="literal">MBRCovers()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_mbrdisjoint"></a><p>
            <a class="indexterm" name="idm46444322380256"></a>

            <a class="link" href="functions.html#function_mbrdisjoint"><code class="literal">MBRDisjoint(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether the minimum bounding
            rectangles of the two geometries
            <em class="replaceable"><code>g1</code></em> and
            <em class="replaceable"><code>g2</code></em> are disjoint (do not
            intersect).
          </p><p>
            <a class="link" href="functions.html#function_mbrdisjoint"><code class="literal">MBRDisjoint()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_mbrequals"></a><p>
            <a class="indexterm" name="idm46444322371024"></a>

            <a class="link" href="functions.html#function_mbrequals"><code class="literal">MBREquals(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether the minimum bounding
            rectangles of the two geometries
            <em class="replaceable"><code>g1</code></em> and
            <em class="replaceable"><code>g2</code></em> are the same.
          </p><p>
            <a class="link" href="functions.html#function_mbrequals"><code class="literal">MBREquals()</code></a> handles its
            arguments as described in the introduction to this section,
            except that it does not return <code class="literal">NULL</code> for
            empty geometry arguments.
          </p></li><li class="listitem"><a name="function_mbrintersects"></a><p>
            <a class="indexterm" name="idm46444322360336"></a>

            <a class="link" href="functions.html#function_mbrintersects"><code class="literal">MBRIntersects(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether the minimum bounding
            rectangles of the two geometries
            <em class="replaceable"><code>g1</code></em> and
            <em class="replaceable"><code>g2</code></em> intersect.
          </p><p>
            <a class="link" href="functions.html#function_mbrintersects"><code class="literal">MBRIntersects()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_mbroverlaps"></a><p>
            <a class="indexterm" name="idm46444322350448"></a>

            <a class="link" href="functions.html#function_mbroverlaps"><code class="literal">MBROverlaps(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Two geometries <span class="emphasis"><em>spatially overlap</em></span> if
            they intersect and their intersection results in a geometry
            of the same dimension but not equal to either of the given
            geometries.
          </p><p>
            This function returns 1 or 0 to indicate whether the minimum
            bounding rectangles of the two geometries
            <em class="replaceable"><code>g1</code></em> and
            <em class="replaceable"><code>g2</code></em> overlap.
          </p><p>
            <a class="link" href="functions.html#function_mbroverlaps"><code class="literal">MBROverlaps()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_mbrtouches"></a><p>
            <a class="indexterm" name="idm46444322339504"></a>

            <a class="link" href="functions.html#function_mbrtouches"><code class="literal">MBRTouches(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Two geometries <span class="emphasis"><em>spatially touch</em></span> if their
            interiors do not intersect, but the boundary of one of the
            geometries intersects either the boundary or the interior of
            the other.
          </p><p>
            This function returns 1 or 0 to indicate whether the minimum
            bounding rectangles of the two geometries
            <em class="replaceable"><code>g1</code></em> and
            <em class="replaceable"><code>g2</code></em> touch.
          </p><p>
            <a class="link" href="functions.html#function_mbrtouches"><code class="literal">MBRTouches()</code></a> handles its
            arguments as described in the introduction to this section.
          </p></li><li class="listitem"><a name="function_mbrwithin"></a><p>
            <a class="indexterm" name="idm46444322328544"></a>

            <a class="link" href="functions.html#function_mbrwithin"><code class="literal">MBRWithin(<em class="replaceable"><code>g1</code></em>,
            <em class="replaceable"><code>g2</code></em>)</code></a>
          </p><p>
            Returns 1 or 0 to indicate whether the minimum bounding
            rectangle of <em class="replaceable"><code>g1</code></em> is within the
            minimum bounding rectangle of <em class="replaceable"><code>g2</code></em>.
            This tests the opposite relationship as
            <a class="link" href="functions.html#function_mbrcontains"><code class="literal">MBRContains()</code></a>.
          </p><p>
            <a class="link" href="functions.html#function_mbrwithin"><code class="literal">MBRWithin()</code></a> handles its
            arguments as described in the introduction to this section.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @g2 = ST_GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);</code></strong>
+--------------------+--------------------+
| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |
+--------------------+--------------------+
|                  1 |                  0 |
+--------------------+--------------------+
</pre></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="spatial-geohash-functions"></a>12.16.10 Spatial Geohash Functions</h3>

</div>

</div>

</div>
<p>
      Geohash is a system for encoding latitude and longitude
      coordinates of arbitrary precision into a text string. Geohash
      values are strings that contain only characters chosen from
      <code class="literal">"0123456789bcdefghjkmnpqrstuvwxyz"</code>.
    </p><p>
      The functions in this section enable manipulation of geohash
      values, which provides applications the capabilities of importing
      and exporting geohash data, and of indexing and searching geohash
      values.
    </p><p>
      Unless otherwise specified, functions in this section handle their
      arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If any argument is <code class="literal">NULL</code>, the return value
          is <code class="literal">NULL</code>.
        </p></li><li class="listitem"><p>
          If any argument is invalid, an error occurs.
        </p></li><li class="listitem"><p>
          If any argument has a longitude or latitude that is out of
          range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If any longitude argument is not in the range (−180,
              180], an
              <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If any latitude argument is not in the range [−90,
              90], an
              <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
              error occurs.
</p></li></ul>
</div>
<p>
          Ranges shown are in degrees. The exact range limits deviate
          slightly due to floating-point arithmetic.
        </p></li><li class="listitem"><p>
          If any point argument does not have SRID 0 or 4326, an
          <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error occurs.
          <em class="replaceable"><code>point</code></em> argument SRID validity is not
          checked.
        </p></li><li class="listitem"><p>
          If any SRID argument refers to an undefined spatial reference
          system (SRS), an
          <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error occurs.
        </p></li><li class="listitem"><p>
          If any SRID argument is not within the range of a 32-bit
          unsigned integer, an
          <a class="link" href="error-handling.html#error_er_data_out_of_range"><code class="literal">ER_DATA_OUT_OF_RANGE</code></a> error
          occurs.
        </p></li><li class="listitem"><p>
          Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
      These geohash functions are available:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-geohash"></a><p>
          <a class="indexterm" name="idm46444322290304"></a>

          <a class="link" href="functions.html#function_st-geohash"><code class="literal">ST_GeoHash(<em class="replaceable"><code>longitude</code></em>,
          <em class="replaceable"><code>latitude</code></em>,
          <em class="replaceable"><code>max_length</code></em>)</code></a>,
          <a class="link" href="functions.html#function_st-geohash"><code class="literal">ST_GeoHash(<em class="replaceable"><code>point</code></em>,
          <em class="replaceable"><code>max_length</code></em>)</code></a>
        </p><p>
          Returns a geohash string in the connection character set and
          collation.
        </p><p>
          For the first syntax, the <em class="replaceable"><code>longitude</code></em>
          must be a number in the range [−180, 180], and the
          <em class="replaceable"><code>latitude</code></em> must be a number in the
          range [−90, 90]. For the second syntax, a
          <code class="literal">POINT</code> value is required, where the X and Y
          coordinates are in the valid ranges for longitude and
          latitude, respectively.
        </p><p>
          The resulting string is no longer than
          <em class="replaceable"><code>max_length</code></em> characters, which has an
          upper limit of 100. The string might be shorter than
          <em class="replaceable"><code>max_length</code></em> characters because the
          algorithm that creates the geohash value continues until it
          has created a string that is either an exact representation of
          the location or <em class="replaceable"><code>max_length</code></em>
          characters, whichever comes first.
        </p><p>
          <a class="link" href="functions.html#function_st-geohash"><code class="literal">ST_GeoHash()</code></a> handles its
          arguments as described in the introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_GeoHash(180,0,10), ST_GeoHash(-180,-90,15);</code></strong>
+----------------------+-------------------------+
| ST_GeoHash(180,0,10) | ST_GeoHash(-180,-90,15) |
+----------------------+-------------------------+
| xbpbpbpbpb           | 000000000000000         |
+----------------------+-------------------------+
</pre></li><li class="listitem"><a name="function_st-latfromgeohash"></a><p>
          <a class="indexterm" name="idm46444322271632"></a>

          <a class="link" href="functions.html#function_st-latfromgeohash"><code class="literal">ST_LatFromGeoHash(<em class="replaceable"><code>geohash_str</code></em>)</code></a>
        </p><p>
          Returns the latitude from a geohash string value, as a
          double-precision number in the range [−90, 90].
        </p><p>
          The <a class="link" href="functions.html#function_st-latfromgeohash"><code class="literal">ST_LatFromGeoHash()</code></a>
          decoding function reads no more than 433 characters from the
          <em class="replaceable"><code>geohash_str</code></em> argument. That
          represents the upper limit on information in the internal
          representation of coordinate values. Characters past the 433rd
          are ignored, even if they are otherwise illegal and produce an
          error.
        </p><p>
          <a class="link" href="functions.html#function_st-latfromgeohash"><code class="literal">ST_LatFromGeoHash()</code></a> handles its
          arguments as described in the introduction to this section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_LatFromGeoHash(ST_GeoHash(45,-20,10));</code></strong>
+------------------------------------------+
| ST_LatFromGeoHash(ST_GeoHash(45,-20,10)) |
+------------------------------------------+
|                                      -20 |
+------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-longfromgeohash"></a><p>
          <a class="indexterm" name="idm46444322257872"></a>

          <a class="link" href="functions.html#function_st-longfromgeohash"><code class="literal">ST_LongFromGeoHash(<em class="replaceable"><code>geohash_str</code></em>)</code></a>
        </p><p>
          Returns the longitude from a geohash string value, as a
          double-precision number in the range [−180, 180].
        </p><p>
          The remarks in the description of
          <a class="link" href="functions.html#function_st-latfromgeohash"><code class="literal">ST_LatFromGeoHash()</code></a> regarding
          the maximum number of characters processed from the
          <em class="replaceable"><code>geohash_str</code></em> argument also apply to
          <a class="link" href="functions.html#function_st-longfromgeohash"><code class="literal">ST_LongFromGeoHash()</code></a>.
        </p><p>
          <a class="link" href="functions.html#function_st-longfromgeohash"><code class="literal">ST_LongFromGeoHash()</code></a> handles
          its arguments as described in the introduction to this
          section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_LongFromGeoHash(ST_GeoHash(45,-20,10));</code></strong>
+-------------------------------------------+
| ST_LongFromGeoHash(ST_GeoHash(45,-20,10)) |
+-------------------------------------------+
|                                        45 |
+-------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-pointfromgeohash"></a><p>
          <a class="indexterm" name="idm46444322243040"></a>

          <a class="link" href="functions.html#function_st-pointfromgeohash"><code class="literal">ST_PointFromGeoHash(<em class="replaceable"><code>geohash_str</code></em>,
          <em class="replaceable"><code>srid</code></em>)</code></a>
        </p><p>
          Returns a <code class="literal">POINT</code> value containing the
          decoded geohash value, given a geohash string value.
        </p><p>
          The X and Y coordinates of the point are the longitude in the
          range [−180, 180] and the latitude in the range
          [−90, 90], respectively.
        </p><p>
          The <em class="replaceable"><code>srid</code></em> argument is an 32-bit
          unsigned integer.
        </p><p>
          The remarks in the description of
          <a class="link" href="functions.html#function_st-latfromgeohash"><code class="literal">ST_LatFromGeoHash()</code></a> regarding
          the maximum number of characters processed from the
          <em class="replaceable"><code>geohash_str</code></em> argument also apply to
          <a class="link" href="functions.html#function_st-pointfromgeohash"><code class="literal">ST_PointFromGeoHash()</code></a>.
        </p><p>
          <a class="link" href="functions.html#function_st-pointfromgeohash"><code class="literal">ST_PointFromGeoHash()</code></a> handles
          its arguments as described in the introduction to this
          section.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @gh = ST_GeoHash(45,-20,10);</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_PointFromGeoHash(@gh,0));</code></strong>
+---------------------------------------+
| ST_AsText(ST_PointFromGeoHash(@gh,0)) |
+---------------------------------------+
| POINT(45 -20)                         |
+---------------------------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="spatial-geojson-functions"></a>12.16.11 Spatial GeoJSON Functions</h3>

</div>

</div>

</div>
<p>
      This section describes functions for converting between GeoJSON
      documents and spatial values. GeoJSON is an open standard for
      encoding geometric/geographical features. For more information,
      see <a class="ulink" href="http://geojson.org" target="_top">http://geojson.org</a>. The functions discussed
      here follow GeoJSON specification revision 1.0.
    </p><p>
      GeoJSON supports the same geometric/geographic data types that
      MySQL supports. Feature and FeatureCollection objects are not
      supported, except that geometry objects are extracted from them.
      CRS support is limited to values that identify an SRID.
    </p><p>
      MySQL also supports a native <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a>
      data type and a set of SQL functions to enable operations on JSON
      values. For more information, see <a class="xref" href="data-types.html#json" title="11.5 The JSON Data Type">Section 11.5, “The JSON Data Type”</a>, and
      <a class="xref" href="functions.html#json-functions" title="12.17 JSON Functions">Section 12.17, “JSON Functions”</a>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-asgeojson"></a><p>
          <a class="indexterm" name="idm46444322218240"></a>

          <a class="link" href="functions.html#function_st-asgeojson"><code class="literal">ST_AsGeoJSON(<em class="replaceable"><code>g</code></em>
          [, <em class="replaceable"><code>max_dec_digits</code></em> [,
          <em class="replaceable"><code>options</code></em>]])</code></a>
        </p><p>
          Generates a GeoJSON object from the geometry
          <em class="replaceable"><code>g</code></em>. The object string has the
          connection character set and collation.
        </p><p>
          If any argument is <code class="literal">NULL</code>, the return value
          is <code class="literal">NULL</code>. If any non-<code class="literal">NULL</code>
          argument is invalid, an error occurs.
        </p><p>
          <em class="replaceable"><code>max_dec_digits</code></em>, if specified,
          limits the number of decimal digits for coordinates and causes
          rounding of output. If not specified, this argument defaults
          to its maximum value of 2<sup>32</sup> −
          1. The minimum is 0.
        </p><p>
          <em class="replaceable"><code>options</code></em>, if specified, is a
          bitmask. The following table shows the permitted flag values.
          If the geometry argument has an SRID of 0, no CRS object is
          produced even for those flag values that request one.
</p>
<div class="informaltable">
<table summary="Option flags for the ST_AsGeoJSON() function."><col width="10%"><col width="90%"><thead><tr>
              <th scope="col">Flag Value</th>
              <th scope="col">Meaning</th>
            </tr></thead><tbody><tr>
              <td scope="row">0</td>
              <td>No options. This is the default if <em class="replaceable"><code>options</code></em> is
                not specified.</td>
            </tr><tr>
              <td scope="row">1</td>
              <td>Add a bounding box to the output.</td>
            </tr><tr>
              <td scope="row">2</td>
              <td>Add a short-format CRS URN to the output. The default format is a short
                format
                (<code class="literal">EPSG:<em class="replaceable"><code>srid</code></em></code>).</td>
            </tr><tr>
              <td scope="row">4</td>
              <td>Add a long-format CRS URN
                (<code class="literal">urn:ogc:def:crs:EPSG::<em class="replaceable"><code>srid</code></em></code>).
                This flag overrides flag 2. For example, option values
                of 5 and 7 mean the same (add a bounding box and a
                long-format CRS URN).</td>
</tr></tbody></table>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)'),2);</code></strong>
+-------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)'),2) |
+-------------------------------------------------------------+
| {"type": "Point", "coordinates": [11.11, 12.22]}            |
+-------------------------------------------------------------+
</pre></li><li class="listitem"><a name="function_st-geomfromgeojson"></a><p>
          <a class="indexterm" name="idm46444322183552"></a>

          <a class="link" href="functions.html#function_st-geomfromgeojson"><code class="literal">ST_GeomFromGeoJSON(<em class="replaceable"><code>str</code></em>
          [, <em class="replaceable"><code>options</code></em> [,
          <em class="replaceable"><code>srid</code></em>]])</code></a>
        </p><p>
          Parses a string <em class="replaceable"><code>str</code></em> representing a
          GeoJSON object and returns a geometry.
        </p><p>
          If any argument is <code class="literal">NULL</code>, the return value
          is <code class="literal">NULL</code>. If any non-<code class="literal">NULL</code>
          argument is invalid, an error occurs.
        </p><p>
          <em class="replaceable"><code>options</code></em>, if given, describes how to
          handle GeoJSON documents that contain geometries with
          coordinate dimensions higher than 2. The following table shows
          the permitted <em class="replaceable"><code>options</code></em> values.
</p>
<div class="informaltable">
<table summary="Option flags for the ST_GeomFromGeoJSON() function."><col width="10%"><col width="90%"><thead><tr>
              <th scope="col">Option Value</th>
              <th scope="col">Meaning</th>
            </tr></thead><tbody><tr>
              <td scope="row">1</td>
              <td>Reject the document and produce an error. This is the default if
                <em class="replaceable"><code>options</code></em> is not specified.</td>
            </tr><tr>
              <td scope="row">2, 3, 4</td>
              <td>Accept the document and strip off the coordinates for higher coordinate
                dimensions.</td>
</tr></tbody></table>
</div>
<p>
          <em class="replaceable"><code>options</code></em> values of 2, 3, and 4
          currently produce the same effect. If geometries with
          coordinate dimensions higher than 2 are supported in the
          future, these values will produce different effects.
        </p><p>
          The <em class="replaceable"><code>srid</code></em> argument, if given, must
          be a 32-bit unsigned integer. If not given, the geometry
          return value has an SRID of 4326.
        </p><p>
          If <em class="replaceable"><code>srid</code></em> refers to an undefined
          spatial reference system (SRS), an
          <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error occurs.
        </p><p>
          For geographic SRS geometry arguments, if any argument has a
          longitude or latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If a longitude value is not in the range (−180,
              180], an
              <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If a latitude value is not in the range [−90, 90],
              an
              <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
              error occurs.
</p></li></ul>
</div>
<p>
          Ranges shown are in degrees. If an SRS uses another unit, the
          range uses the corresponding values in its unit. The exact
          range limits deviate slightly due to floating-point
          arithmetic.
        </p><p>
          GeoJSON geometry, feature, and feature collection objects may
          have a <code class="literal">crs</code> property. The parsing function
          parses named CRS URNs in the
          <code class="literal">urn:ogc:def:crs:EPSG::<em class="replaceable"><code>srid</code></em></code>
          and <code class="literal">EPSG:<em class="replaceable"><code>srid</code></em></code>
          namespaces, but not CRSs given as link objects. Also,
          <code class="literal">urn:ogc:def:crs:OGC:1.3:CRS84</code> is recognized
          as SRID 4326. If an object has a CRS that is not understood,
          an error occurs, with the exception that if the optional
          <em class="replaceable"><code>srid</code></em> argument is given, any CRS is
          ignored even if it is invalid.
        </p><p>
          If a <code class="literal">crs</code> member that specifies an SRID
          different from the top-level object SRID is found at a lower
          level of the GeoJSON document, an
          <a class="link" href="error-handling.html#error_er_invalid_geojson_crs_not_top_level"><code class="literal">ER_INVALID_GEOJSON_CRS_NOT_TOP_LEVEL</code></a>
          error occurs.
        </p><p>
          As specified in the GeoJSON specification, parsing is case
          sensitive for the <code class="literal">type</code> member of the
          GeoJSON input (<code class="literal">Point</code>,
          <code class="literal">LineString</code>, and so forth). The
          specification is silent regarding case sensitivity for other
          parsing, which in MySQL is not case-sensitive.
        </p><p>
          This example shows the parsing result for a simple GeoJSON
          object:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @json = '{ "type": "Point", "coordinates": [102.0, 0.0]}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_GeomFromGeoJSON(@json));</code></strong>
+--------------------------------------+
| ST_AsText(ST_GeomFromGeoJSON(@json)) |
+--------------------------------------+
| POINT(102 0)                         |
+--------------------------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="spatial-convenience-functions"></a>12.16.12 Spatial Convenience Functions</h3>

</div>

</div>

</div>
<p>
      The functions in this section provide convenience operations on
      geometry values.
    </p><p>
      Unless otherwise specified, functions in this section handle their
      arguments as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If any argument is <code class="literal">NULL</code>, the return value
          is <code class="literal">NULL</code>.
        </p></li><li class="listitem"><p>
          If any geometry argument is not a syntactically well-formed
          geometry, an
          <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
          occurs.
        </p></li><li class="listitem"><p>
          If any geometry argument has an SRID value that refers to an
          undefined spatial reference system (SRS), an
          <a class="link" href="error-handling.html#error_er_srs_not_found"><code class="literal">ER_SRS_NOT_FOUND</code></a> error occurs.
        </p></li><li class="listitem"><p>
          For functions that take multiple geometry arguments, if those
          arguments do not have the same SRID, an
          <a class="link" href="error-handling.html#error_er_gis_different_srids"><code class="literal">ER_GIS_DIFFERENT_SRIDS</code></a> error
          occurs.
        </p></li><li class="listitem"><p>
          Otherwise, the return value is non-<code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
      These convenience functions are available:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_st-distance-sphere"></a><p>
          <a class="indexterm" name="idm46444322121376"></a>

          <a class="link" href="functions.html#function_st-distance-sphere"><code class="literal">ST_Distance_Sphere(<em class="replaceable"><code>g1</code></em>,
          <em class="replaceable"><code>g2</code></em> [,
          <em class="replaceable"><code>radius</code></em>])</code></a>
        </p><p>
          Returns the mimimum spherical distance between
          <code class="literal">Point</code> or <code class="literal">MultiPoint</code>
          arguments on a sphere, in meters. (For general-purpose
          distance calculations, see the
          <a class="link" href="functions.html#function_st-distance"><code class="literal">ST_Distance()</code></a> function.) The
          optional <em class="replaceable"><code>radius</code></em> argument should be
          given in meters.
        </p><p>
          If both geometry parameters are valid Cartesian
          <code class="literal">Point</code> or <code class="literal">MultiPoint</code>
          values in SRID 0, the return value is shortest distance
          between the two geometries on a sphere with the provided
          radius. If omitted, the default radius is 6,370,986 meters,
          Point X and Y coordinates are interpreted as longitude and
          latitude, respectively, in degrees.
        </p><p>
          If both geometry parameters are valid <code class="literal">Point</code>
          or <code class="literal">MultiPoint</code> values in a geographic
          spatial reference system (SRS), the return value is the
          shortest distance between the two geometries on a sphere with
          the provided radius. If omitted, the default radius is equal
          to the mean radius, defined as (2a+b)/3, where a is the
          semi-major axis and b is the semi-minor axis of the SRS.
        </p><p>
          <a class="link" href="functions.html#function_st-distance-sphere"><code class="literal">ST_Distance_Sphere()</code></a> handles
          its arguments as described in the introduction to this
          section, with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Supported geometry argument combinations are
              <code class="literal">Point</code> and <code class="literal">Point</code>, or
              <code class="literal">Point</code> and <code class="literal">MultiPoint</code>
              (in any argument order). If at least one of the geometries
              is neither <code class="literal">Point</code> nor
              <code class="literal">MultiPoint</code>, and its SRID is 0, an
              <a class="link" href="error-handling.html#error_er_not_implemented_for_cartesian_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_CARTESIAN_SRS</code></a>
              error occurs. If at least one of the geometries is neither
              <code class="literal">Point</code> nor
              <code class="literal">MultiPoint</code>, and its SRID refers to a
              geographic SRS, an
              <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
              error occurs. If any geometry refers to a projected SRS,
              an
              <a class="link" href="error-handling.html#error_er_not_implemented_for_projected_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_PROJECTED_SRS</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If any argument has a longitude or latitude that is out of
              range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  If any longitude argument is not in the range
                  (−180, 180], an
                  <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                  error occurs.
                </p></li><li class="listitem"><p>
                  If any latitude argument is not in the range
                  [−90, 90], an
                  <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                  error occurs.
</p></li></ul>
</div>
<p>
              Ranges shown are in degrees. If an SRS uses another unit,
              the range uses the corresponding values in its unit. The
              exact range limits deviate slightly due to floating-point
              arithmetic.
            </p></li><li class="listitem"><p>
              If the <em class="replaceable"><code>radius</code></em> argument is
              present but not positive, an
              <a class="link" href="error-handling.html#error_er_nonpositive_radius"><code class="literal">ER_NONPOSITIVE_RADIUS</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              If the distance exceeds the range of a double-precision
              number, an
              <a class="link" href="error-handling.html#error_er_std_overflow_error"><code class="literal">ER_STD_OVERFLOW_ERROR</code></a>
              error occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @pt1 = ST_GeomFromText('POINT(0 0)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @pt2 = ST_GeomFromText('POINT(180 0)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_Distance_Sphere(@pt1, @pt2);</code></strong>
+--------------------------------+
| ST_Distance_Sphere(@pt1, @pt2) |
+--------------------------------+
|             20015042.813723423 |
+--------------------------------+
</pre></li><li class="listitem"><a name="function_st-isvalid"></a><p>
          <a class="indexterm" name="idm46444322076336"></a>

          <a class="link" href="functions.html#function_st-isvalid"><code class="literal">ST_IsValid(<em class="replaceable"><code>g</code></em>)</code></a>
        </p><p>
          Returns 1 if the argument is geometrically valid, 0 if the
          argument is not geometrically valid. Geometry validity is
          defined by the OGC specification.
        </p><p>
          The only valid empty geometry is represented in the form of an
          empty geometry collection value.
          <a class="link" href="functions.html#function_st-isvalid"><code class="literal">ST_IsValid()</code></a> returns 1 in this
          case. MySQL does not support GIS <code class="literal">EMPTY</code>
          values such as <code class="literal">POINT EMPTY</code>.
        </p><p>
          <a class="link" href="functions.html#function_st-isvalid"><code class="literal">ST_IsValid()</code></a> handles its
          arguments as described in the introduction to this section,
          with this exception:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If the geometry has a geographic SRS with a longitude or
              latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  If any longitude argument is not in the range
                  (−180, 180], an
                  <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                  error occurs.
                </p></li><li class="listitem"><p>
                  If any latitude argument is not in the range
                  [−90, 90], an
                  <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                  error occurs.
</p></li></ul>
</div>
<p>
              Ranges shown are in degrees. If an SRS uses another unit,
              the range uses the corresponding values in its unit. The
              exact range limits deviate slightly due to floating-point
              arithmetic.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls1 = ST_GeomFromText('LINESTRING(0 0,-0.00 0,0.0 0)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @ls2 = ST_GeomFromText('LINESTRING(0 0, 1 1)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_IsValid(@ls1);</code></strong>
+------------------+
| ST_IsValid(@ls1) |
+------------------+
|                0 |
+------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_IsValid(@ls2);</code></strong>
+------------------+
| ST_IsValid(@ls2) |
+------------------+
|                1 |
+------------------+
</pre></li><li class="listitem"><a name="function_st-makeenvelope"></a><p>
          <a class="indexterm" name="idm46444322052064"></a>

          <a class="link" href="functions.html#function_st-makeenvelope"><code class="literal">ST_MakeEnvelope(<em class="replaceable"><code>pt1</code></em>,
          <em class="replaceable"><code>pt2</code></em>)</code></a>
        </p><p>
          Returns the rectangle that forms the envelope around two
          points, as a <code class="literal">Point</code>,
          <code class="literal">LineString</code>, or <code class="literal">Polygon</code>.
        </p><p>
          Calculations are done using the Cartesian coordinate system
          rather than on a sphere, spheroid, or on earth.
        </p><p>
          Given two points <em class="replaceable"><code>pt1</code></em> and
          <em class="replaceable"><code>pt2</code></em>,
          <a class="link" href="functions.html#function_st-makeenvelope"><code class="literal">ST_MakeEnvelope()</code></a> creates the
          result geometry on an abstract plane like this:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If <em class="replaceable"><code>pt1</code></em> and
              <em class="replaceable"><code>pt2</code></em> are equal, the result is
              the point <em class="replaceable"><code>pt1</code></em>.
            </p></li><li class="listitem"><p>
              Otherwise, if <code class="literal">(<em class="replaceable"><code>pt1</code></em>,
              <em class="replaceable"><code>pt2</code></em>)</code> is a vertical or
              horizontal line segment, the result is the line segment
              <code class="literal">(<em class="replaceable"><code>pt1</code></em>,
              <em class="replaceable"><code>pt2</code></em>)</code>.
            </p></li><li class="listitem"><p>
              Otherwise, the result is a polygon using
              <em class="replaceable"><code>pt1</code></em> and
              <em class="replaceable"><code>pt2</code></em> as diagonal points.
</p></li></ul>
</div>
<p>
          The result geometry has an SRID of 0.
        </p><p>
          <a class="link" href="functions.html#function_st-makeenvelope"><code class="literal">ST_MakeEnvelope()</code></a> handles its
          arguments as described in the introduction to this section,
          with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If the arguments are not <code class="literal">Point</code> values,
              an <a class="link" href="error-handling.html#error_er_wrong_arguments"><code class="literal">ER_WRONG_ARGUMENTS</code></a>
              error occurs.
            </p></li><li class="listitem"><p>
              An <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a>
              error occurs for the additional condition that any
              coordinate value of the two points is infinite or
              <code class="literal">NaN</code>.
            </p></li><li class="listitem"><p>
              If any geometry has an SRID value for a geographic spatial
              reference system (SRS), an
              <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
              error occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @pt1 = ST_GeomFromText('POINT(0 0)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @pt2 = ST_GeomFromText('POINT(1 1)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_MakeEnvelope(@pt1, @pt2));</code></strong>
+----------------------------------------+
| ST_AsText(ST_MakeEnvelope(@pt1, @pt2)) |
+----------------------------------------+
| POLYGON((0 0,1 0,1 1,0 1,0 0))         |
+----------------------------------------+
</pre></li><li class="listitem"><a name="function_st-simplify"></a><p>
          <a class="indexterm" name="idm46444322016272"></a>

          <a class="link" href="functions.html#function_st-simplify"><code class="literal">ST_Simplify(<em class="replaceable"><code>g</code></em>,
          <em class="replaceable"><code>max_distance</code></em>)</code></a>
        </p><p>
          Simplifies a geometry using the Douglas-Peucker algorithm and
          returns a simplified value of the same type.
        </p><p>
          The geometry may be any geometry type, although the
          Douglas-Peucker algorithm may not actually process every type.
          A geometry collection is processed by giving its components
          one by one to the simplification algorithm, and the returned
          geometries are put into a geometry collection as result.
        </p><p>
          The <em class="replaceable"><code>max_distance</code></em> argument is the
          distance (in units of the input coordinates) of a vertex to
          other segments to be removed. Vertices within this distance of
          the simplified linestring are removed.
        </p><p>
          According to Boost.Geometry, geometries might become invalid
          as a result of the simplification process, and the process
          might create self-intersections. To check the validity of the
          result, pass it to
          <a class="link" href="functions.html#function_st-isvalid"><code class="literal">ST_IsValid()</code></a>.
        </p><p>
          <a class="link" href="functions.html#function_st-simplify"><code class="literal">ST_Simplify()</code></a> handles its
          arguments as described in the introduction to this section,
          with this exception:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If the <em class="replaceable"><code>max_distance</code></em> argument is
              not positive, or is <code class="literal">NaN</code>, an
              <a class="link" href="error-handling.html#error_er_wrong_arguments"><code class="literal">ER_WRONG_ARGUMENTS</code></a> error
              occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @g = ST_GeomFromText('LINESTRING(0 0,0 1,1 1,1 2,2 2,2 3,3 3)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Simplify(@g, 0.5));</code></strong>
+---------------------------------+
| ST_AsText(ST_Simplify(@g, 0.5)) |
+---------------------------------+
| LINESTRING(0 0,0 1,1 1,2 3,3 3) |
+---------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Simplify(@g, 1.0));</code></strong>
+---------------------------------+
| ST_AsText(ST_Simplify(@g, 1.0)) |
+---------------------------------+
| LINESTRING(0 0,3 3)             |
+---------------------------------+
</pre></li><li class="listitem"><a name="function_st-validate"></a><p>
          <a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate(<em class="replaceable"><code>g</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444321993328"></a><p>
          Validates a geometry according to the OGC specification. A
          geometry can be syntactically well-formed (WKB value plus
          SRID) but geometrically invalid. For example, this polygon is
          geometrically invalid: <code class="literal">POLYGON((0 0, 0 0, 0 0, 0 0, 0
          0))</code>
        </p><p>
          <a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate()</code></a> returns the
          geometry if it is syntactically well-formed and is
          geometrically valid, <code class="literal">NULL</code> if the argument
          is not syntactically well-formed or is not geometrically valid
          or is <code class="literal">NULL</code>.
        </p><p>
          <a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate()</code></a> can be used to
          filter out invalid geometry data, although at a cost. For
          applications that require more precise results not tainted by
          invalid data, this penalty may be worthwhile.
        </p><p>
          If the geometry argument is valid, it is returned as is,
          except that if an input <code class="literal">Polygon</code> or
          <code class="literal">MultiPolygon</code> has clockwise rings, those
          rings are reversed before checking for validity. If the
          geometry is valid, the value with the reversed rings is
          returned.
        </p><p>
          The only valid empty geometry is represented in the form of an
          empty geometry collection value.
          <a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate()</code></a> returns it
          directly without further checks in this case.
        </p><p>
          As of MySQL 8.0.13,
          <a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate()</code></a> handles its
          arguments as described in the introduction to this section,
          with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If the geometry has a geographic SRS with a longitude or
              latitude that is out of range, an error occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  If any longitude argument is not in the range
                  (−180, 180], an
                  <a class="link" href="error-handling.html#error_er_longitude_out_of_range"><code class="literal">ER_LONGITUDE_OUT_OF_RANGE</code></a>
                  error occurs.
                </p></li><li class="listitem"><p>
                  If any latitude argument is not in the range
                  [−90, 90], an
                  <a class="link" href="error-handling.html#error_er_latitude_out_of_range"><code class="literal">ER_LATITUDE_OUT_OF_RANGE</code></a>
                  error occurs.
</p></li></ul>
</div>
<p>
              Ranges shown are in degrees. The exact range limits
              deviate slightly due to floating-point arithmetic.
</p></li></ul>
</div>
<p>
          Prior to MySQL 8.0.13,
          <a class="link" href="functions.html#function_st-validate"><code class="literal">ST_Validate()</code></a> handles its
          arguments as described in the introduction to this section,
          with these exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              If the geometry is not syntactically well-formed, the
              return value is <code class="literal">NULL</code>. An
              <a class="link" href="error-handling.html#error_er_gis_invalid_data"><code class="literal">ER_GIS_INVALID_DATA</code></a> error
              does not occur.
            </p></li><li class="listitem"><p>
              If the geometry has an SRID value for a geographic spatial
              reference system (SRS), an
              <a class="link" href="error-handling.html#error_er_not_implemented_for_geographic_srs"><code class="literal">ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS</code></a>
              error occurs.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @ls1 = ST_GeomFromText('LINESTRING(0 0)');</code></strong>
mysql&gt; <strong class="userinput"><code>SET @ls2 = ST_GeomFromText('LINESTRING(0 0, 1 1)');</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Validate(@ls1));</code></strong>
+------------------------------+
| ST_AsText(ST_Validate(@ls1)) |
+------------------------------+
| NULL                         |
+------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT ST_AsText(ST_Validate(@ls2));</code></strong>
+------------------------------+
| ST_AsText(ST_Validate(@ls2)) |
+------------------------------+
| LINESTRING(0 0,1 1)          |
+------------------------------+
</pre></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="json-functions"></a>12.17 JSON Functions</h2>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#json-function-reference">12.17.1 JSON Function Reference</a></span></dt><dt><span class="section"><a href="functions.html#json-creation-functions">12.17.2 Functions That Create JSON Values</a></span></dt><dt><span class="section"><a href="functions.html#json-search-functions">12.17.3 Functions That Search JSON Values</a></span></dt><dt><span class="section"><a href="functions.html#json-modification-functions">12.17.4 Functions That Modify JSON Values</a></span></dt><dt><span class="section"><a href="functions.html#json-attribute-functions">12.17.5 Functions That Return JSON Value Attributes</a></span></dt><dt><span class="section"><a href="functions.html#json-table-functions">12.17.6 JSON Table Functions</a></span></dt><dt><span class="section"><a href="functions.html#json-validation-functions">12.17.7 JSON Schema Validation Functions</a></span></dt><dt><span class="section"><a href="functions.html#json-utility-functions">12.17.8 JSON Utility Functions</a></span></dt></dl>
</div>
<a class="indexterm" name="idm46444321958272"></a><p>
    The functions described in this section perform operations on JSON
    values. For discussion of the <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a>
    data type and additional examples showing how to use these
    functions, see <a class="xref" href="data-types.html#json" title="11.5 The JSON Data Type">Section 11.5, “The JSON Data Type”</a>.
  </p><p>
    For functions that take a JSON argument, an error occurs if the
    argument is not a valid JSON value. Arguments parsed as JSON are
    indicated by <em class="replaceable"><code>json_doc</code></em>; arguments
    indicated by <em class="replaceable"><code>val</code></em> are not parsed.
  </p><p>
    A set of spatial functions for operating on GeoJSON values is also
    available. See <a class="xref" href="functions.html#spatial-geojson-functions" title="12.16.11 Spatial GeoJSON Functions">Section 12.16.11, “Spatial GeoJSON Functions”</a>.
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-function-reference"></a>12.17.1 JSON Function Reference</h3>
</div>
</div>
</div>
<a class="indexterm" name="idm46444321950928"></a>
<div class="table">
<a name="idm46444321949856"></a><p class="title"><b>Table 12.21 JSON Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists all JSON functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a></td>
<td>
      Return value from JSON column after evaluating path; equivalent to
      JSON_EXTRACT().
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_json-inline-path"><code class="literal">-&gt;&gt;</code></a></td>
<td>
      Return value from JSON column after evaluating path and unquoting
      the result; equivalent to JSON_UNQUOTE(JSON_EXTRACT()).
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-array"><code class="literal">JSON_ARRAY()</code></a></td>
<td>
      Create JSON array
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-array-append"><code class="literal">JSON_ARRAY_APPEND()</code></a></td>
<td>
      Append data to JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-array-insert"><code class="literal">JSON_ARRAY_INSERT()</code></a></td>
<td>
      Insert into JSON array
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-contains"><code class="literal">JSON_CONTAINS()</code></a></td>
<td>
      Whether JSON document contains specific object at path
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-contains-path"><code class="literal">JSON_CONTAINS_PATH()</code></a></td>
<td>
      Whether JSON document contains any data at path
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-depth"><code class="literal">JSON_DEPTH()</code></a></td>
<td>
      Maximum depth of JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-extract"><code class="literal">JSON_EXTRACT()</code></a></td>
<td>
      Return data from JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-insert"><code class="literal">JSON_INSERT()</code></a></td>
<td>
      Insert data into JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-keys"><code class="literal">JSON_KEYS()</code></a></td>
<td>
      Array of keys from JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-length"><code class="literal">JSON_LENGTH()</code></a></td>
<td>
      Number of elements in JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-merge"><code class="literal">JSON_MERGE()</code></a> (deprecated)</td>
<td>
      Merge JSON documents, preserving duplicate keys. Deprecated
      synonym for JSON_MERGE_PRESERVE()
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-merge-patch"><code class="literal">JSON_MERGE_PATCH()</code></a></td>
<td>
      Merge JSON documents, replacing values of duplicate keys
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-merge-preserve"><code class="literal">JSON_MERGE_PRESERVE()</code></a></td>
<td>
      Merge JSON documents, preserving duplicate keys
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-object"><code class="literal">JSON_OBJECT()</code></a></td>
<td>
      Create JSON object
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-overlaps"><code class="literal">JSON_OVERLAPS()</code></a> (introduced 8.0.17)</td>
<td>
      Compares two JSON documents, returns TRUE (1) if these have any
      key-value pairs or array elements in common, otherwise FALSE (0)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-pretty"><code class="literal">JSON_PRETTY()</code></a></td>
<td>
      Print a JSON document in human-readable format
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-quote"><code class="literal">JSON_QUOTE()</code></a></td>
<td>
      Quote JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-remove"><code class="literal">JSON_REMOVE()</code></a></td>
<td>
      Remove data from JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a></td>
<td>
      Replace values in JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-schema-valid"><code class="literal">JSON_SCHEMA_VALID()</code></a> (introduced 8.0.17)</td>
<td>
      Validate JSON document against JSON schema; returns TRUE/1 if
      document validates against schema, or FALSE/0 if it does not
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-schema-validation-report"><code class="literal">JSON_SCHEMA_VALIDATION_REPORT()</code></a> (introduced 8.0.17)</td>
<td>
      Validate JSON document against JSON schema; returns report in JSON
      format on outcome on validation including success or failure and
      reasons for failure
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-search"><code class="literal">JSON_SEARCH()</code></a></td>
<td>
      Path to value within JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a></td>
<td>
      Insert data into JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-storage-free"><code class="literal">JSON_STORAGE_FREE()</code></a></td>
<td>
      Freed space within binary representation of JSON column value
      following partial update
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-storage-size"><code class="literal">JSON_STORAGE_SIZE()</code></a></td>
<td>
      Space used for storage of binary representation of a JSON document
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-table"><code class="literal">JSON_TABLE()</code></a></td>
<td>
      Return data from a JSON expression as a relational table
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-type"><code class="literal">JSON_TYPE()</code></a></td>
<td>
      Type of JSON value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-unquote"><code class="literal">JSON_UNQUOTE()</code></a></td>
<td>
      Unquote JSON value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-valid"><code class="literal">JSON_VALID()</code></a></td>
<td>
      Whether JSON value is valid
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-value"><code class="literal">JSON_VALUE()</code></a> (introduced 8.0.21)</td>
<td>
      Extract value from JSON document at location pointed to by path
      provided; return this value as VARCHAR(512) or specified type
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#operator_member-of"><code class="literal">MEMBER OF()</code></a> (introduced 8.0.17)</td>
<td>
      Returns true (1) if first operand matches any element of JSON
      array passed as second operand, otherwise returns false (0)
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      MySQL supports two aggregate JSON functions
      <a class="link" href="functions.html#function_json-arrayagg"><code class="literal">JSON_ARRAYAGG()</code></a> and
      <a class="link" href="functions.html#function_json-objectagg"><code class="literal">JSON_OBJECTAGG()</code></a>. See
      <a class="xref" href="functions.html#group-by-functions-and-modifiers" title="12.20 Aggregate (GROUP BY) Functions">Section 12.20, “Aggregate (GROUP BY) Functions”</a>, for
      descriptions of these.
    </p><p>
      MySQL also supports <span class="quote">“<span class="quote">pretty-printing</span>”</span> of JSON values
      in an easy-to-read format, using the
      <a class="link" href="functions.html#function_json-pretty"><code class="literal">JSON_PRETTY()</code></a> function. You can see
      how much storage space a given JSON value takes up, and how much
      space remains for additional storage, using
      <a class="link" href="functions.html#function_json-storage-size"><code class="literal">JSON_STORAGE_SIZE()</code></a> and
      <a class="link" href="functions.html#function_json-storage-free"><code class="literal">JSON_STORAGE_FREE()</code></a>, respectively.
      For complete descriptions of these functions, see
      <a class="xref" href="functions.html#json-utility-functions" title="12.17.8 JSON Utility Functions">Section 12.17.8, “JSON Utility Functions”</a>.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-creation-functions"></a>12.17.2 Functions That Create JSON Values</h3>

</div>

</div>

</div>
<p>
      The functions listed in this section compose JSON values from
      component elements.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_json-array"></a><p>
          <a class="indexterm" name="idm46444321820544"></a>

          <a class="link" href="functions.html#function_json-array"><code class="literal">JSON_ARRAY([<em class="replaceable"><code>val</code></em>[,
          <em class="replaceable"><code>val</code></em>] ...])</code></a>
        </p><p>
          Evaluates a (possibly empty) list of values and returns a JSON
          array containing those values.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME());</code></strong>
+---------------------------------------------+
| JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME()) |
+---------------------------------------------+
| [1, "abc", null, true, "11:30:24.000000"]   |
+---------------------------------------------+
</pre></li><li class="listitem"><a name="function_json-object"></a><p>
          <a class="indexterm" name="idm46444321809136"></a>

          <a class="link" href="functions.html#function_json-object"><code class="literal">JSON_OBJECT([<em class="replaceable"><code>key</code></em>,
          <em class="replaceable"><code>val</code></em>[,
          <em class="replaceable"><code>key</code></em>,
          <em class="replaceable"><code>val</code></em>] ...])</code></a>
        </p><p>
          Evaluates a (possibly empty) list of key-value pairs and
          returns a JSON object containing those pairs. An error occurs
          if any key name is <code class="literal">NULL</code> or the number of
          arguments is odd.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECT('id', 87, 'name', 'carrot');</code></strong>
+-----------------------------------------+
| JSON_OBJECT('id', 87, 'name', 'carrot') |
+-----------------------------------------+
| {"id": 87, "name": "carrot"}            |
+-----------------------------------------+
</pre></li><li class="listitem"><a name="function_json-quote"></a><p>
          <a class="indexterm" name="idm46444321796112"></a>

          <a class="link" href="functions.html#function_json-quote"><code class="literal">JSON_QUOTE(<em class="replaceable"><code>string</code></em>)</code></a>
        </p><p>
          Quotes a string as a JSON value by wrapping it with double
          quote characters and escaping interior quote and other
          characters, then returning the result as a
          <code class="literal">utf8mb4</code> string. Returns
          <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>.
        </p><p>
          This function is typically used to produce a valid JSON string
          literal for inclusion within a JSON document.
        </p><p>
          Certain special characters are escaped with backslashes per
          the escape sequences shown in
          <a class="xref" href="functions.html#json-unquote-character-escape-sequences" title="Table 12.22 JSON_UNQUOTE() Special Character Escape Sequences">Table 12.22, “JSON_UNQUOTE() Special Character Escape Sequences”</a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_QUOTE('null'), JSON_QUOTE('"null"');</code></strong>
+--------------------+----------------------+
| JSON_QUOTE('null') | JSON_QUOTE('"null"') |
+--------------------+----------------------+
| "null"             | "\"null\""           |
+--------------------+----------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_QUOTE('[1, 2, 3]');</code></strong>
+-------------------------+
| JSON_QUOTE('[1, 2, 3]') |
+-------------------------+
| "[1, 2, 3]"             |
+-------------------------+
</pre></li></ul>
</div>
<p>
      You can also obtain JSON values by casting values of other types
      to the <code class="literal">JSON</code> type using
      <a class="link" href="functions.html#function_cast"><code class="literal">CAST(<em class="replaceable"><code>value</code></em> AS
      JSON)</code></a>; see
      <a class="xref" href="data-types.html#json-converting-between-types" title="Converting between JSON and non-JSON values">Converting between JSON and non-JSON values</a>, for more
      information.
    </p><p>
      Two aggregate functions generating JSON values are available.
      <a class="link" href="functions.html#function_json-arrayagg"><code class="literal">JSON_ARRAYAGG()</code></a> returns a result
      set as a single JSON array, and
      <a class="link" href="functions.html#function_json-objectagg"><code class="literal">JSON_OBJECTAGG()</code></a> returns a result
      set as a single JSON object. For more information, see
      <a class="xref" href="functions.html#group-by-functions-and-modifiers" title="12.20 Aggregate (GROUP BY) Functions">Section 12.20, “Aggregate (GROUP BY) Functions”</a>.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-search-functions"></a>12.17.3 Functions That Search JSON Values</h3>

</div>

</div>

</div>
<p>
      The functions in this section perform search or comparison
      operations on JSON values to extract data from them, report
      whether data exists at a location within them, or report the path
      to data within them. The <a class="link" href="functions.html#operator_member-of"><code class="literal">MEMBER OF()</code></a>
      operator is also documented herein.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_json-contains"></a><p>
          <a class="indexterm" name="idm46444321769040"></a>

          <a class="link" href="functions.html#function_json-contains"><code class="literal">JSON_CONTAINS(<em class="replaceable"><code>target</code></em>,
          <em class="replaceable"><code>candidate</code></em>[,
          <em class="replaceable"><code>path</code></em>])</code></a>
        </p><p>
          Indicates by returning 1 or 0 whether a given
          <em class="replaceable"><code>candidate</code></em> JSON document is
          contained within a <em class="replaceable"><code>target</code></em> JSON
          document, or—if a <em class="replaceable"><code>path</code></em>
          argument was supplied—whether the candidate is found at
          a specific path within the target. Returns
          <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>, or if the path argument does not
          identify a section of the target document. An error occurs if
          <em class="replaceable"><code>target</code></em> or
          <em class="replaceable"><code>candidate</code></em> is not a valid JSON
          document, or if the <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or contains a
          <code class="literal">*</code> or <code class="literal">**</code> wildcard.
        </p><p>
          To check only whether any data exists at the path, use
          <a class="link" href="functions.html#function_json-contains-path"><code class="literal">JSON_CONTAINS_PATH()</code></a> instead.
        </p><p>
          The following rules define containment:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              A candidate scalar is contained in a target scalar if and
              only if they are comparable and are equal. Two scalar
              values are comparable if they have the same
              <a class="link" href="functions.html#function_json-type"><code class="literal">JSON_TYPE()</code></a> types, with the
              exception that values of types <code class="literal">INTEGER</code>
              and <code class="literal">DECIMAL</code> are also comparable to each
              other.
            </p></li><li class="listitem"><p>
              A candidate array is contained in a target array if and
              only if every element in the candidate is contained in
              some element of the target.
            </p></li><li class="listitem"><p>
              A candidate nonarray is contained in a target array if and
              only if the candidate is contained in some element of the
              target.
            </p></li><li class="listitem"><p>
              A candidate object is contained in a target object if and
              only if for each key in the candidate there is a key with
              the same name in the target and the value associated with
              the candidate key is contained in the value associated
              with the target key.
</p></li></ul>
</div>
<p>
          Otherwise, the candidate value is not contained in the target
          document.
        </p><p>
          Starting with MySQL 8.0.17, queries using
          <code class="literal">JSON_CONTAINS()</code> on
          <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a> tables can be optimized
          using multi-valued indexes; see
          <a class="xref" href="sql-statements.html#create-index-multi-valued" title="Multi-Valued Indexes">Multi-Valued Indexes</a>, for more
          information.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';</code></strong>
mysql&gt; <strong class="userinput"><code>SET @j2 = '1';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS(@j, @j2, '$.a');</code></strong>
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.a') |
+-------------------------------+
|                             1 |
+-------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS(@j, @j2, '$.b');</code></strong>
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.b') |
+-------------------------------+
|                             0 |
+-------------------------------+

mysql&gt; <strong class="userinput"><code>SET @j2 = '{"d": 4}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS(@j, @j2, '$.a');</code></strong>
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.a') |
+-------------------------------+
|                             0 |
+-------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS(@j, @j2, '$.c');</code></strong>
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.c') |
+-------------------------------+
|                             1 |
+-------------------------------+
</pre></li><li class="listitem"><a name="function_json-contains-path"></a><p>
          <a class="indexterm" name="idm46444321732672"></a>

          <a class="link" href="functions.html#function_json-contains-path"><code class="literal">JSON_CONTAINS_PATH(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>one_or_all</code></em>,
          <em class="replaceable"><code>path</code></em>[,
          <em class="replaceable"><code>path</code></em>] ...)</code></a>
        </p><p>
          Returns 0 or 1 to indicate whether a JSON document contains
          data at a given path or paths. Returns <code class="literal">NULL</code>
          if any argument is <code class="literal">NULL</code>. An error occurs if
          the <em class="replaceable"><code>json_doc</code></em> argument is not a
          valid JSON document, any <em class="replaceable"><code>path</code></em>
          argument is not a valid path expression, or
          <em class="replaceable"><code>one_or_all</code></em> is not
          <code class="literal">'one'</code> or <code class="literal">'all'</code>.
        </p><p>
          To check for a specific value at a path, use
          <a class="link" href="functions.html#function_json-contains"><code class="literal">JSON_CONTAINS()</code></a> instead.
        </p><p>
          The return value is 0 if no specified path exists within the
          document. Otherwise, the return value depends on the
          <em class="replaceable"><code>one_or_all</code></em> argument:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">'one'</code>: 1 if at least one path exists
              within the document, 0 otherwise.
            </p></li><li class="listitem"><p>
              <code class="literal">'all'</code>: 1 if all paths exist within the
              document, 0 otherwise.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e');</code></strong>
+---------------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e') |
+---------------------------------------------+
|                                           1 |
+---------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e');</code></strong>
+---------------------------------------------+
| JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e') |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS_PATH(@j, 'one', '$.c.d');</code></strong>
+----------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.c.d') |
+----------------------------------------+
|                                      1 |
+----------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a.d');</code></strong>
+----------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.a.d') |
+----------------------------------------+
|                                      0 |
+----------------------------------------+
</pre></li><li class="listitem"><a name="function_json-extract"></a><p>
          <a class="indexterm" name="idm46444321705360"></a>

          <a class="link" href="functions.html#function_json-extract"><code class="literal">JSON_EXTRACT(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>[,
          <em class="replaceable"><code>path</code></em>] ...)</code></a>
        </p><p>
          Returns data from a JSON document, selected from the parts of
          the document matched by the <em class="replaceable"><code>path</code></em>
          arguments. Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code> or no paths locate a value in the
          document. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or any <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression.
        </p><p>
          The return value consists of all values matched by the
          <em class="replaceable"><code>path</code></em> arguments. If it is possible
          that those arguments could return multiple values, the matched
          values are autowrapped as an array, in the order corresponding
          to the paths that produced them. Otherwise, the return value
          is the single matched value.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]');</code></strong>
+--------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]') |
+--------------------------------------------+
| 20                                         |
+--------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]');</code></strong>
+----------------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]') |
+----------------------------------------------------+
| [20, 10]                                           |
+----------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]');</code></strong>
+-----------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]') |
+-----------------------------------------------+
| [30, 40]                                      |
+-----------------------------------------------+
</pre><p>
          MySQL supports the
          <a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a>
          operator as shorthand for this function as used with 2
          arguments where the left hand side is a
          <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> column identifier (not an
          expression) and the right hand side is the JSON path to be
          matched within the column.
        </p></li><li class="listitem"><a name="operator_json-column-path"></a><p>
          <a class="indexterm" name="idm46444321683376"></a>

          <a class="link" href="functions.html#operator_json-column-path"><code class="literal"><em class="replaceable"><code>column</code></em>-&gt;<em class="replaceable"><code>path</code></em></code></a>
        </p><p>
          The
          <a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a>
          operator serves as an alias for the
          <a class="link" href="functions.html#function_json-extract"><code class="literal">JSON_EXTRACT()</code></a> function when
          used with two arguments, a column identifier on the left and a
          JSON path on the right that is evaluated against the JSON
          document (the column value). You can use such expressions in
          place of column identifiers wherever they occur in SQL
          statements.
        </p><p>
          The two <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> statements shown
          here produce the same output:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT c, JSON_EXTRACT(c, "$.id"), g</code></strong>
     &gt; <strong class="userinput"><code>FROM jemp</code></strong>
     &gt; <strong class="userinput"><code>WHERE JSON_EXTRACT(c, "$.id") &gt; 1</code></strong>
     &gt; <strong class="userinput"><code>ORDER BY JSON_EXTRACT(c, "$.name");</code></strong>
+-------------------------------+-----------+------+
| c                             | c-&gt;"$.id" | g    |
+-------------------------------+-----------+------+
| {"id": "3", "name": "Barney"} | "3"       |    3 |
| {"id": "4", "name": "Betty"}  | "4"       |    4 |
| {"id": "2", "name": "Wilma"}  | "2"       |    2 |
+-------------------------------+-----------+------+
3 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT c, c-&gt;"$.id", g</code></strong>
     &gt; <strong class="userinput"><code>FROM jemp</code></strong>
     &gt; <strong class="userinput"><code>WHERE c-&gt;"$.id" &gt; 1</code></strong>
     &gt; <strong class="userinput"><code>ORDER BY c-&gt;"$.name";</code></strong>
+-------------------------------+-----------+------+
| c                             | c-&gt;"$.id" | g    |
+-------------------------------+-----------+------+
| {"id": "3", "name": "Barney"} | "3"       |    3 |
| {"id": "4", "name": "Betty"}  | "4"       |    4 |
| {"id": "2", "name": "Wilma"}  | "2"       |    2 |
+-------------------------------+-----------+------+
3 rows in set (0.00 sec)
</pre><p>
          This functionality is not limited to
          <code class="literal">SELECT</code>, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>ALTER TABLE jemp ADD COLUMN n INT;</code></strong>
Query OK, 0 rows affected (0.68 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>UPDATE jemp SET n=1 WHERE c-&gt;"$.id" = "4";</code></strong>
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT c, c-&gt;"$.id", g, n</code></strong>
     &gt; <strong class="userinput"><code>FROM jemp</code></strong>
     &gt; <strong class="userinput"><code>WHERE JSON_EXTRACT(c, "$.id") &gt; 1</code></strong>
     &gt; <strong class="userinput"><code>ORDER BY c-&gt;"$.name";</code></strong>
+-------------------------------+-----------+------+------+
| c                             | c-&gt;"$.id" | g    | n    |
+-------------------------------+-----------+------+------+
| {"id": "3", "name": "Barney"} | "3"       |    3 | NULL |
| {"id": "4", "name": "Betty"}  | "4"       |    4 |    1 |
| {"id": "2", "name": "Wilma"}  | "2"       |    2 | NULL |
+-------------------------------+-----------+------+------+
3 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>DELETE FROM jemp WHERE c-&gt;"$.id" = "4";</code></strong>
Query OK, 1 row affected (0.04 sec)

mysql&gt; <strong class="userinput"><code>SELECT c, c-&gt;"$.id", g, n</code></strong>
     &gt; <strong class="userinput"><code>FROM jemp</code></strong>
     &gt; <strong class="userinput"><code>WHERE JSON_EXTRACT(c, "$.id") &gt; 1</code></strong>
     &gt; <strong class="userinput"><code>ORDER BY c-&gt;"$.name";</code></strong>
+-------------------------------+-----------+------+------+
| c                             | c-&gt;"$.id" | g    | n    |
+-------------------------------+-----------+------+------+
| {"id": "3", "name": "Barney"} | "3"       |    3 | NULL |
| {"id": "2", "name": "Wilma"}  | "2"       |    2 | NULL |
+-------------------------------+-----------+------+------+
2 rows in set (0.00 sec)
</pre><p>
          (See <a class="xref" href="sql-statements.html#json-column-indirect-index" title="Indexing a Generated Column to Provide a JSON Column Index">Indexing a Generated Column to Provide a JSON Column Index</a>, for the
          statements used to create and populate the table just shown.)
        </p><p>
          This also works with JSON array values, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE tj10 (a JSON, b INT);</code></strong>
Query OK, 0 rows affected (0.26 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO tj10</code></strong>
     &gt; <strong class="userinput"><code>VALUES ("[3,10,5,17,44]", 33), ("[3,10,5,17,[22,44,66]]", 0);</code></strong>
Query OK, 1 row affected (0.04 sec)

mysql&gt; <strong class="userinput"><code>SELECT a-&gt;"$[4]" FROM tj10;</code></strong>
+--------------+
| a-&gt;"$[4]"    |
+--------------+
| 44           |
| [22, 44, 66] |
+--------------+
2 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT * FROM tj10 WHERE a-&gt;"$[0]" = 3;</code></strong>
+------------------------------+------+
| a                            | b    |
+------------------------------+------+
| [3, 10, 5, 17, 44]           |   33 |
| [3, 10, 5, 17, [22, 44, 66]] |    0 |
+------------------------------+------+
2 rows in set (0.00 sec)
</pre><p>
          Nested arrays are supported. An expression using
          <code class="literal">-&gt;</code> evaluates as <code class="literal">NULL</code>
          if no matching key is found in the target JSON document, as
          shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM tj10 WHERE a-&gt;"$[4][1]" IS NOT NULL;</code></strong>
+------------------------------+------+
| a                            | b    |
+------------------------------+------+
| [3, 10, 5, 17, [22, 44, 66]] |    0 |
+------------------------------+------+

mysql&gt; <strong class="userinput"><code>SELECT a-&gt;"$[4][1]" FROM tj10;</code></strong>
+--------------+
| a-&gt;"$[4][1]" |
+--------------+
| NULL         |
| 44           |
+--------------+
2 rows in set (0.00 sec)
</pre><p>
          This is the same behavior as seen in such cases when using
          <code class="literal">JSON_EXTRACT()</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_EXTRACT(a, "$[4][1]") FROM tj10;</code></strong>
+----------------------------+
| JSON_EXTRACT(a, "$[4][1]") |
+----------------------------+
| NULL                       |
| 44                         |
+----------------------------+
2 rows in set (0.00 sec)
</pre></li><li class="listitem"><a name="operator_json-inline-path"></a><p>
          <a class="indexterm" name="idm46444321632720"></a>

          <a class="link" href="functions.html#operator_json-inline-path"><code class="literal"><em class="replaceable"><code>column</code></em>-&gt;&gt;<em class="replaceable"><code>path</code></em></code></a>
        </p><p>
          This is an improved, unquoting extraction operator. Whereas
          the <code class="literal">-&gt;</code> operator simply extracts a value,
          the <code class="literal">-&gt;&gt;</code> operator in addition unquotes
          the extracted result. In other words, given a
          <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> column value
          <em class="replaceable"><code>column</code></em> and a path expression
          <em class="replaceable"><code>path</code></em>, the following three
          expressions return the same value:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <a class="link" href="functions.html#function_json-unquote"><code class="literal">JSON_UNQUOTE(</code></a>
              <a class="link" href="functions.html#function_json-extract"><code class="literal">JSON_EXTRACT(<em class="replaceable"><code>column</code></em>,
              <em class="replaceable"><code>path</code></em>) )</code></a>
            </p></li><li class="listitem"><p>
              <code class="literal">JSON_UNQUOTE(<em class="replaceable"><code>column</code></em></code>
              <a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a>
              <code class="literal"><em class="replaceable"><code>path</code></em>)</code>
            </p></li><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>column</code></em>-&gt;&gt;<em class="replaceable"><code>path</code></em></code>
</p></li></ul>
</div>
<p>
          The <code class="literal">-&gt;&gt;</code> operator can be used wherever
          <code class="literal">JSON_UNQUOTE(JSON_EXTRACT())</code> would be
          allowed. This includes (but is not limited to)
          <code class="literal">SELECT</code> lists, <code class="literal">WHERE</code> and
          <code class="literal">HAVING</code> clauses, and <code class="literal">ORDER
          BY</code> and <code class="literal">GROUP BY</code> clauses.
        </p><p>
          The next few statements demonstrate some
          <code class="literal">-&gt;&gt;</code> operator equivalences with other
          expressions in the <a class="link" href="programs.html#mysql" title="4.5.1 mysql — The MySQL Command-Line Client"><span class="command"><strong>mysql</strong></span></a> client:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM jemp WHERE g &gt; 2;</code></strong>
+-------------------------------+------+
| c                             | g    |
+-------------------------------+------+
| {"id": "3", "name": "Barney"} |    3 |
| {"id": "4", "name": "Betty"}  |    4 |
+-------------------------------+------+
2 rows in set (0.01 sec)

mysql&gt; <strong class="userinput"><code>SELECT c-&gt;'$.name' AS name</code></strong>
    -&gt;     <strong class="userinput"><code>FROM jemp WHERE g &gt; 2;</code></strong>
+----------+
| name     |
+----------+
| "Barney" |
| "Betty"  |
+----------+
2 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_UNQUOTE(c-&gt;'$.name') AS name</code></strong>
    -&gt;     <strong class="userinput"><code>FROM jemp WHERE g &gt; 2;</code></strong>
+--------+
| name   |
+--------+
| Barney |
| Betty  |
+--------+
2 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT c-&gt;&gt;'$.name' AS name</code></strong>
    -&gt;     <strong class="userinput"><code>FROM jemp WHERE g &gt; 2;</code></strong>
+--------+
| name   |
+--------+
| Barney |
| Betty  |
+--------+
2 rows in set (0.00 sec)
</pre><p>
          See <a class="xref" href="sql-statements.html#json-column-indirect-index" title="Indexing a Generated Column to Provide a JSON Column Index">Indexing a Generated Column to Provide a JSON Column Index</a>, for the SQL
          statements used to create and populate the
          <code class="literal">jemp</code> table in the set of examples just
          shown.
        </p><p>
          This operator can also be used with JSON arrays, as shown
          here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE tj10 (a JSON, b INT);</code></strong>
Query OK, 0 rows affected (0.26 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO tj10 VALUES</code></strong>
    -&gt;     <strong class="userinput"><code>('[3,10,5,"x",44]', 33),</code></strong>
    -&gt;     <strong class="userinput"><code>('[3,10,5,17,[22,"y",66]]', 0);</code></strong>
Query OK, 2 rows affected (0.04 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT a-&gt;"$[3]", a-&gt;"$[4][1]" FROM tj10;</code></strong>
+-----------+--------------+
| a-&gt;"$[3]" | a-&gt;"$[4][1]" |
+-----------+--------------+
| "x"       | NULL         |
| 17        | "y"          |
+-----------+--------------+
2 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT a-&gt;&gt;"$[3]", a-&gt;&gt;"$[4][1]" FROM tj10;</code></strong>
+------------+---------------+
| a-&gt;&gt;"$[3]" | a-&gt;&gt;"$[4][1]" |
+------------+---------------+
| x          | NULL          |
| 17         | y             |
+------------+---------------+
2 rows in set (0.00 sec)
</pre><p>
          As with
          <a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a>,
          the <code class="literal">-&gt;&gt;</code> operator is always expanded
          in the output of <a class="link" href="sql-statements.html#explain" title="13.8.2 EXPLAIN Statement"><code class="literal">EXPLAIN</code></a>, as
          the following example demonstrates:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>EXPLAIN SELECT c-&gt;&gt;'$.name' AS name</code></strong>
    -&gt;     <strong class="userinput"><code>FROM jemp WHERE g &gt; 2\G</code></strong>
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: jemp
   partitions: NULL
         type: range
possible_keys: i
          key: i
      key_len: 5
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS\G</code></strong>
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select
json_unquote(json_extract(`jtest`.`jemp`.`c`,'$.name')) AS `name` from
`jtest`.`jemp` where (`jtest`.`jemp`.`g` &gt; 2)
1 row in set (0.00 sec)
</pre><p>
          This is similar to how MySQL expands the
          <a class="link" href="functions.html#operator_json-column-path"><code class="literal">-&gt;</code></a>
          operator in the same circumstances.
        </p></li><li class="listitem"><a name="function_json-keys"></a><p>
          <a class="indexterm" name="idm46444321575328"></a>

          <a class="link" href="functions.html#function_json-keys"><code class="literal">JSON_KEYS(<em class="replaceable"><code>json_doc</code></em>[,
          <em class="replaceable"><code>path</code></em>])</code></a>
        </p><p>
          Returns the keys from the top-level value of a JSON object as
          a JSON array, or, if a <em class="replaceable"><code>path</code></em>
          argument is given, the top-level keys from the selected path.
          Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>, the
          <em class="replaceable"><code>json_doc</code></em> argument is not an object,
          or <em class="replaceable"><code>path</code></em>, if given, does not locate
          an object. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or the <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or contains a
          <code class="literal">*</code> or <code class="literal">**</code> wildcard.
        </p><p>
          The result array is empty if the selected object is empty. If
          the top-level value has nested subobjects, the return value
          does not include keys from those subobjects.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}');</code></strong>
+---------------------------------------+
| JSON_KEYS('{"a": 1, "b": {"c": 30}}') |
+---------------------------------------+
| ["a", "b"]                            |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b');</code></strong>
+----------------------------------------------+
| JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b') |
+----------------------------------------------+
| ["c"]                                        |
+----------------------------------------------+
</pre></li><li class="listitem"><a name="function_json-overlaps"></a><p>
          <a class="indexterm" name="idm46444321556768"></a>

          <a class="link" href="functions.html#function_json-overlaps"><code class="literal">JSON_OVERLAPS(<em class="replaceable"><code>json_doc1</code></em>,
          <em class="replaceable"><code>json_doc2</code></em>)</code></a>
        </p><p>
          Compares two JSON documents. Returns true (1) if the two
          document have any key-value pairs or array elements in common.
          If both arguments are scalars, the function performs a simple
          equality test.
        </p><p>
          This function serves as counterpart to
          <a class="link" href="functions.html#function_json-contains"><code class="literal">JSON_CONTAINS()</code></a>, which requires
          all elements of the array searched for to be present in the
          array searched in. Thus, <code class="literal">JSON_CONTAINS()</code>
          performs an <code class="literal">AND</code> operation on search keys,
          while <code class="literal">JSON_OVERLAPS()</code> performs an
          <code class="literal">OR</code> operation.
        </p><p>
          Queries on JSON columns of <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a>
          tables using <code class="literal">JSON_OVERLAPS()</code> in the
          <code class="literal">WHERE</code> clause can be optimized using
          multi-valued indexes.
          <a class="xref" href="sql-statements.html#create-index-multi-valued" title="Multi-Valued Indexes">Multi-Valued Indexes</a>, provides detailed
          information and examples.
        </p><p>
          When two comparing two arrays,
          <code class="literal">JSON_OVERLAPS()</code> returns true if they share
          one or more array elements in common, and false if they do
          not:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]");</code></strong>
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]") |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]");</code></strong>
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]") |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]");</code></strong>
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]") |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          Partial matches are treated as no match, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('[[1,2],[3,4],5]', '[1,[2,3],[4,5]]');</code></strong>
+-----------------------------------------------------+
| JSON_OVERLAPS('[[1,2],[3,4],5]', '[1,[2,3],[4,5]]') |
+-----------------------------------------------------+
|                                                   0 |
+-----------------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          When comparing objects, the result is true if they have at
          least one key-value pair in common.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"c":1,"e":10,"f":1,"d":10}');</code></strong>
+-----------------------------------------------------------------------+
| JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"c":1,"e":10,"f":1,"d":10}') |
+-----------------------------------------------------------------------+
|                                                                     1 |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"a":5,"e":10,"f":1,"d":20}');</code></strong>
+-----------------------------------------------------------------------+
| JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"a":5,"e":10,"f":1,"d":20}') |
+-----------------------------------------------------------------------+
|                                                                     0 |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          If two scalars are used as the arguments to the function,
          <code class="literal">JSON_OVERLAPS()</code> performs a simple test for
          equality:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('5', '5');</code></strong>
+-------------------------+
| JSON_OVERLAPS('5', '5') |
+-------------------------+
|                       1 |
+-------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('5', '6');</code></strong>
+-------------------------+
| JSON_OVERLAPS('5', '6') |
+-------------------------+
|                       0 |
+-------------------------+
1 row in set (0.00 sec)
</pre><p>
          When comparing a scalar with an array,
          <code class="literal">JSON_OVERLAPS()</code> attempts to treat the
          scalar as an array element. In this example, the second
          argument <code class="literal">6</code> is interpreted as
          <code class="literal">[6]</code>, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('[4,5,6,7]', '6');</code></strong>
+---------------------------------+
| JSON_OVERLAPS('[4,5,6,7]', '6') |
+---------------------------------+
|                               1 |
+---------------------------------+
1 row in set (0.00 sec)
</pre><p>
          The function does not perform type conversions:
        </p><pre class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('[4,5,"6",7]', '6');</code></strong>
+-----------------------------------+
| JSON_OVERLAPS('[4,5,"6",7]', '6') |
+-----------------------------------+
|                                 0 |
+-----------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_OVERLAPS('[4,5,6,7]', '"6"');</code></strong>
+-----------------------------------+
| JSON_OVERLAPS('[4,5,6,7]', '"6"') |
+-----------------------------------+
|                                 0 |
+-----------------------------------+
1 row in set (0.00 sec)
</pre><p>
          <code class="literal">JSON_OVERLAPS()</code> was added in MySQL 8.0.17.
        </p></li><li class="listitem"><a name="function_json-search"></a><p>
          <a class="indexterm" name="idm46444321513136"></a>

          <a class="link" href="functions.html#function_json-search"><code class="literal">JSON_SEARCH(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>one_or_all</code></em>,
          <em class="replaceable"><code>search_str</code></em>[,
          <em class="replaceable"><code>escape_char</code></em>[,
          <em class="replaceable"><code>path</code></em>] ...])</code></a>
        </p><p>
          Returns the path to the given string within a JSON document.
          Returns <code class="literal">NULL</code> if any of the
          <em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>search_str</code></em>, or
          <em class="replaceable"><code>path</code></em> arguments are
          <code class="literal">NULL</code>; no <em class="replaceable"><code>path</code></em>
          exists within the document; or
          <em class="replaceable"><code>search_str</code></em> is not found. An error
          occurs if the <em class="replaceable"><code>json_doc</code></em> argument is
          not a valid JSON document, any <em class="replaceable"><code>path</code></em>
          argument is not a valid path expression,
          <em class="replaceable"><code>one_or_all</code></em> is not
          <code class="literal">'one'</code> or <code class="literal">'all'</code>, or
          <em class="replaceable"><code>escape_char</code></em> is not a constant
          expression.
        </p><p>
          The <em class="replaceable"><code>one_or_all</code></em> argument affects the
          search as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">'one'</code>: The search terminates after the
              first match and returns one path string. It is undefined
              which match is considered first.
            </p></li><li class="listitem"><p>
              <code class="literal">'all'</code>: The search returns all matching
              path strings such that no duplicate paths are included. If
              there are multiple strings, they are autowrapped as an
              array. The order of the array elements is undefined.
</p></li></ul>
</div>
<p>
          Within the <em class="replaceable"><code>search_str</code></em> search string
          argument, the <code class="literal">%</code> and <code class="literal">_</code>
          characters work as for the <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a>
          operator: <code class="literal">%</code> matches any number of
          characters (including zero characters), and
          <code class="literal">_</code> matches exactly one character.
        </p><p>
          To specify a literal <code class="literal">%</code> or
          <code class="literal">_</code> character in the search string, precede
          it by the escape character. The default is
          <code class="literal">\</code> if the
          <em class="replaceable"><code>escape_char</code></em> argument is missing or
          <code class="literal">NULL</code>. Otherwise,
          <em class="replaceable"><code>escape_char</code></em> must be a constant that
          is empty or one character.
        </p><p>
          For more information about matching and escape character
          behavior, see the description of
          <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a> in
          <a class="xref" href="functions.html#string-comparison-functions" title="12.7.1 String Comparison Functions and Operators">Section 12.7.1, “String Comparison Functions and Operators”</a>. For escape
          character handling, a difference from the
          <a class="link" href="functions.html#operator_like"><code class="literal">LIKE</code></a> behavior is that the escape
          character for <a class="link" href="functions.html#function_json-search"><code class="literal">JSON_SEARCH()</code></a>
          must evaluate to a constant at compile time, not just at
          execution time. For example, if
          <a class="link" href="functions.html#function_json-search"><code class="literal">JSON_SEARCH()</code></a> is used in a
          prepared statement and the
          <em class="replaceable"><code>escape_char</code></em> argument is supplied
          using a <code class="literal">?</code> parameter, the parameter value
          might be constant at execution time, but is not at compile
          time.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]';</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'one', 'abc');</code></strong>
+-------------------------------+
| JSON_SEARCH(@j, 'one', 'abc') |
+-------------------------------+
| "$[0]"                        |
+-------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', 'abc');</code></strong>
+-------------------------------+
| JSON_SEARCH(@j, 'all', 'abc') |
+-------------------------------+
| ["$[0]", "$[2].x"]            |
+-------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', 'ghi');</code></strong>
+-------------------------------+
| JSON_SEARCH(@j, 'all', 'ghi') |
+-------------------------------+
| NULL                          |
+-------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '10');</code></strong>
+------------------------------+
| JSON_SEARCH(@j, 'all', '10') |
+------------------------------+
| "$[1][0].k"                  |
+------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$');</code></strong>
+-----------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$') |
+-----------------------------------------+
| "$[1][0].k"                             |
+-----------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*]');</code></strong>
+--------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[*]') |
+--------------------------------------------+
| "$[1][0].k"                                |
+--------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$**.k');</code></strong>
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$**.k') |
+---------------------------------------------+
| "$[1][0].k"                                 |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k');</code></strong>
+-------------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k') |
+-------------------------------------------------+
| "$[1][0].k"                                     |
+-------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1]');</code></strong>
+--------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[1]') |
+--------------------------------------------+
| "$[1][0].k"                                |
+--------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]');</code></strong>
+-----------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]') |
+-----------------------------------------------+
| "$[1][0].k"                                   |
+-----------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]');</code></strong>
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]') |
+---------------------------------------------+
| "$[2].x"                                    |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '%a%');</code></strong>
+-------------------------------+
| JSON_SEARCH(@j, 'all', '%a%') |
+-------------------------------+
| ["$[0]", "$[2].x"]            |
+-------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '%b%');</code></strong>
+-------------------------------+
| JSON_SEARCH(@j, 'all', '%b%') |
+-------------------------------+
| ["$[0]", "$[2].x", "$[3].y"]  |
+-------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]');</code></strong>
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]') |
+---------------------------------------------+
| "$[0]"                                      |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]');</code></strong>
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]') |
+---------------------------------------------+
| "$[2].x"                                    |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]');</code></strong>
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]') |
+---------------------------------------------+
| NULL                                        |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[1]');</code></strong>
+-------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', '', '$[1]') |
+-------------------------------------------+
| NULL                                      |
+-------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[3]');</code></strong>
+-------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', '', '$[3]') |
+-------------------------------------------+
| "$[3].y"                                  |
+-------------------------------------------+
</pre><p>
          For more information about the JSON path syntax supported by
          MySQL, including rules governing the wildcard operators
          <code class="literal">*</code> and <code class="literal">**</code>, see
          <a class="xref" href="data-types.html#json-path-syntax" title="JSON Path Syntax">JSON Path Syntax</a>.
        </p></li><li class="listitem"><a name="function_json-value"></a><p>
          <a class="indexterm" name="idm46444321448320"></a>

          <a class="link" href="functions.html#function_json-value"><code class="literal">JSON_VALUE(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>)</code></a>
        </p><p>
          Extracts a value from a JSON document at the path given in the
          specified document, and returns the extracted value,
          optionally converting it to a desired type. The complete
          syntax is shown here:
        </p><pre data-lang="clike" class="programlisting">JSON_VALUE(<em class="replaceable"><code>json_doc</code></em>, <em class="replaceable"><code>path</code></em> [RETURNING <em class="replaceable"><code>type</code></em>] [<em class="replaceable"><code>on_empty</code></em>] [<em class="replaceable"><code>on_error</code></em>])

<em class="replaceable"><code>on_empty</code></em>:
    {NULL | ERROR | DEFAULT <em class="replaceable"><code>value</code></em>} ON EMPTY

<em class="replaceable"><code>on_error</code></em>:
    {NULL | ERROR | DEFAULT <em class="replaceable"><code>value</code></em>} ON ERROR
</pre><p>
          <em class="replaceable"><code>json_doc</code></em> is a valid JSON document.
        </p><p>
          <em class="replaceable"><code>path</code></em> is a JSON path pointing to a
          location in the document.
        </p><p>
          <em class="replaceable"><code>type</code></em> is one of the following data
          types:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a>
            </p></li><li class="listitem"><p>
              <code class="literal">SIGNED</code>
            </p></li><li class="listitem"><p>
              <code class="literal">UNSIGNED</code>
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a>
            </p></li><li class="listitem"><p>
              <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a>
</p></li></ul>
</div>
<p>
          The types just listed are the same as the (non-array) types
          supported by the <a class="link" href="functions.html#function_cast"><code class="literal">CAST()</code></a>
          function.
        </p><p>
          If not specified by a <code class="literal">RETURNING</code> clause, the
          <code class="literal">JSON_VALUE()</code> function's return type is
          <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR(512)</code></a>. When no character
          set is specified for the return type,
          <code class="literal">JSON_VALUE()</code> uses
          <code class="literal">utf8mb4</code> with the binary collation, which is
          case sensitive; if <code class="literal">utf8mb4</code> is specified as
          the character set for the result, the server uses the default
          collation for this character set, which is case insensitive.
        </p><p>
          <em class="replaceable"><code>on_empty</code></em>, if specified, determines
          how <code class="literal">JSON_VALUE()</code> behaves when no data is
          found at the path given; this clause takes one of the
          following values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">NULL ON EMPTY</code>: The function returns
              <code class="literal">NULL</code>; this is the default <code class="literal">ON
              EMPTY</code> behavior.
            </p></li><li class="listitem"><p>
              <code class="literal">DEFAULT <em class="replaceable"><code>value</code></em> ON
              EMPTY</code>: the provided
              <em class="replaceable"><code>value</code></em> is returned. The
              value's type must match that of the return type.
            </p></li><li class="listitem"><p>
              <code class="literal">ERROR ON EMPTY</code>: The function throws an
              error.
</p></li></ul>
</div>
<p>
          If used, <em class="replaceable"><code>on_error</code></em> takes one of the
          following values with the corresponding outcome when an error
          occurs, as listed here:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">NULL ON ERROR</code>:
              <code class="literal">JSON_VALUE()</code> returns
              <code class="literal">NULL</code>; this is the default behavior if
              no <code class="literal">ON ERROR</code> clause is used.
            </p></li><li class="listitem"><p>
              <code class="literal">DEFAULT <em class="replaceable"><code>value</code></em> ON
              ERROR</code>: This is the value returned; its value
              must match that of the return type.
            </p></li><li class="listitem"><p>
              <code class="literal">ERROR ON ERROR</code>: An error is thrown.
</p></li></ul>
</div>
<p>
          <code class="literal">ON EMPTY</code>, if used, must precede any
          <code class="literal">ON ERROR</code> clause. Specifying them in the
          wrong order results in a syntax error.
        </p><p><b>Error handling. </b>
            In general, errors are handled by
            <code class="literal">JSON_VALUE()</code> as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              All JSON input (document and path) is checked for
              validity. If any of it is not valid, an SQL error is
              thrown without triggering the <code class="literal">ON ERROR</code>
              clause.
            </p></li><li class="listitem"><p>
              <code class="literal">ON ERROR</code> is triggered whenever any of
              the following events occur:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  Attempting to extract an object or an array, such as
                  that resulting from a path that resolves to multiple
                  locations within the JSON document
                </p></li><li class="listitem"><p>
                  Conversion errors, such as attempting to convert
                  <code class="literal">'asdf'</code> to an
                  <code class="literal">UNSIGNED</code> value
                </p></li><li class="listitem"><p>
                  Truncation of values
</p></li></ul>
</div>
</li><li class="listitem"><p>
              A conversion error always triggers a warning even if
              <code class="literal">NULL ON ERROR</code> or <code class="literal">DEFAULT ...
              ON ERROR</code> is specified.
            </p></li><li class="listitem"><p>
              The <code class="literal">ON EMPTY</code> clause is triggered when
              the source JSON document (<em class="replaceable"><code>expr</code></em>)
              contains no data at the specified location
              (<em class="replaceable"><code>path</code></em>).
</p></li></ul>
</div>
<p><b>Examples. </b>
            Two simple examples are shown here:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_VALUE('{"fname": "Joe", "lname": "Palmer"}', '$.fname');</code></strong>
+--------------------------------------------------------------+
| JSON_VALUE('{"fname": "Joe", "lname": "Palmer"}', '$.fname') |
+--------------------------------------------------------------+
| Joe                                                          |
+--------------------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price'</code></strong>
    -&gt; <strong class="userinput"><code>RETURNING DECIMAL(4,2)) AS price;</code></strong>
+-------+
| price |
+-------+
| 49.95 |
+-------+
</pre><p>
          The statement <code class="literal">SELECT
          JSON_VALUE(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em> RETURNING
          <em class="replaceable"><code>type</code></em>)</code> is equivalent to
          the following statement:
        </p><pre data-lang="sql" class="programlisting">SELECT CAST(
    JSON_UNQUOTE( JSON_EXTRACT(<em class="replaceable"><code>json_doc</code></em>, <em class="replaceable"><code>path</code></em>) )
    AS <em class="replaceable"><code>type</code></em>
);
</pre><p>
          <code class="literal">JSON_VALUE()</code> simplifies creating indexes on
          JSON columns by making it unnecessary in many cases to create
          a generated column and then an index on the generated column.
          You can do this when creating a table <code class="literal">t1</code>
          that has a <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> column by
          creating an index on an expression that uses
          <code class="literal">JSON_VALUE()</code> operating on that column (with
          a path that matches a value in that column), as shown here:
        </p><pre data-lang="sql" class="programlisting">CREATE TABLE t1(
    j JSON,
    INDEX i1 ( (JSON_VALUE(j, '$.id' RETURNING UNSIGNED)) )
);</pre><p>
          The following <a class="link" href="sql-statements.html#explain" title="13.8.2 EXPLAIN Statement"><code class="literal">EXPLAIN</code></a> output
          shows that a query against <code class="literal">t1</code> employing the
          index expression in the <code class="literal">WHERE</code> clause uses
          the index thus created:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; EXPLAIN SELECT * FROM t1
    -&gt;     WHERE JSON_VALUE(j, '$.id' RETURNING UNSIGNED) = 123\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: i1
          key: i1
      key_len: 9
          ref: const
         rows: 1
     filtered: 100.00
        Extra: NULL</pre><p>
          This achieves much the same effect as creating a table
          <code class="literal">t2</code> with an index on a generated column (see
          <a class="xref" href="sql-statements.html#json-column-indirect-index" title="Indexing a Generated Column to Provide a JSON Column Index">Indexing a Generated Column to Provide a JSON Column Index</a>), like this one:
        </p><pre data-lang="sql" class="programlisting">CREATE TABLE t2 (
    j JSON,
    g INT GENERATED ALWAYS AS (j-&gt;"$.id"),
    INDEX i1 (j)
);</pre><p>
          The <a class="link" href="sql-statements.html#explain" title="13.8.2 EXPLAIN Statement"><code class="literal">EXPLAIN</code></a> output for a query
          against this table, referencing the generated column, shows
          that the index is used in the same way as for the previous
          query against table <code class="literal">t1</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; EXPLAIN SELECT * FROM t2 WHERE g  = 123\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t2
   partitions: NULL
         type: ref
possible_keys: i1
          key: i1
      key_len: 5
          ref: const
         rows: 1
     filtered: 100.00
        Extra: NULL</pre><p>
          For information about using indexes on generated columns for
          indirect indexing of JSON columns, see
          <a class="xref" href="sql-statements.html#json-column-indirect-index" title="Indexing a Generated Column to Provide a JSON Column Index">Indexing a Generated Column to Provide a JSON Column Index</a>.
        </p></li><li class="listitem"><a name="operator_member-of"></a><p>
          <a class="indexterm" name="idm46444321341904"></a>

          <a class="link" href="functions.html#operator_member-of"><code class="literal"><em class="replaceable"><code>value</code></em>
          MEMBER OF(<em class="replaceable"><code>json_array</code></em>)</code></a>
        </p><p>
          Returns true (1) if <em class="replaceable"><code>value</code></em> is an
          element of <em class="replaceable"><code>json_array</code></em>, otherwise
          returns false (0). <em class="replaceable"><code>value</code></em> must be a
          scalar or a JSON document; if it is a scalar, the operator
          attempts to treat it as an element of a JSON array.
        </p><p>
          Queries using <code class="literal">MEMBER OF()</code> on JSON columns
          of <a class="link" href="innodb-storage-engine.html" title="Chapter 15 The InnoDB Storage Engine"><code class="literal">InnoDB</code></a> tables in the
          <code class="literal">WHERE</code> clause can be optimized using
          multi-valued indexes. See
          <a class="xref" href="sql-statements.html#create-index-multi-valued" title="Multi-Valued Indexes">Multi-Valued Indexes</a>, for detailed
          information and examples.
        </p><p>
          Simple scalars are treated as array values, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 17 MEMBER OF('[23, "abc", 17, "ab", 10]');</code></strong>
+-------------------------------------------+
| 17 MEMBER OF('[23, "abc", 17, "ab", 10]') |
+-------------------------------------------+
|                                         1 |
+-------------------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT 'ab' MEMBER OF('[23, "abc", 17, "ab", 10]');</code></strong>
+---------------------------------------------+
| 'ab' MEMBER OF('[23, "abc", 17, "ab", 10]') |
+---------------------------------------------+
|                                           1 |
+---------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          Partial matches of array element values do not match:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 7 MEMBER OF('[23, "abc", 17, "ab", 10]');</code></strong>
+------------------------------------------+
| 7 MEMBER OF('[23, "abc", 17, "ab", 10]') |
+------------------------------------------+
|                                        0 |
+------------------------------------------+
1 row in set (0.00 sec)
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 'a' MEMBER OF('[23, "abc", 17, "ab", 10]');</code></strong>
+--------------------------------------------+
| 'a' MEMBER OF('[23, "abc", 17, "ab", 10]') |
+--------------------------------------------+
|                                          0 |
+--------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          Conversions to and from string types are not performed:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt; <strong class="userinput"><code>17 MEMBER OF('[23, "abc", "17", "ab", 10]'),</code></strong>
    -&gt; <strong class="userinput"><code>"17" MEMBER OF('[23, "abc", 17, "ab", 10]')\G</code></strong>
*************************** 1. row ***************************
17 MEMBER OF('[23, "abc", "17", "ab", 10]'): 0
"17" MEMBER OF('[23, "abc", 17, "ab", 10]'): 0
1 row in set (0.00 sec)
</pre><p>
          To use this operator with a value which itself an array, it is
          necessary to cast it explicitly as a JSON array. You can do
          this with <a class="link" href="functions.html#function_cast"><code class="literal">CAST(... AS JSON)</code></a>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT CAST('[4,5]' AS JSON) MEMBER OF('[[3,4],[4,5]]');</code></strong>
+--------------------------------------------------+
| CAST('[4,5]' AS JSON) MEMBER OF('[[3,4],[4,5]]') |
+--------------------------------------------------+
|                                                1 |
+--------------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          It is also possible to perform the necessary cast using the
          <a class="link" href="functions.html#function_json-array"><code class="literal">JSON_ARRAY()</code></a> function, like
          this:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY(4,5) MEMBER OF('[[3,4],[4,5]]');</code></strong>
+--------------------------------------------+
| JSON_ARRAY(4,5) MEMBER OF('[[3,4],[4,5]]') |
+--------------------------------------------+
|                                          1 |
+--------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          Any JSON objects used as values to be tested or which appear
          in the target array must be coerced to the correct type using
          <code class="literal">CAST(... AS JSON)</code> or
          <a class="link" href="functions.html#function_json-object"><code class="literal">JSON_OBJECT()</code></a>. In addition, a
          target array containing JSON objects must itself be cast using
          <code class="literal">JSON_ARRAY</code>. This is demonstrated in the
          following sequence of statements:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @a = CAST('{"a":1}' AS JSON);</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @b = JSON_OBJECT("b", 2);</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @c = JSON_ARRAY(17, @b, "abc", @a, 23);</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @a MEMBER OF(@c), @b MEMBER OF(@c);</code></strong>
+------------------+------------------+
| @a MEMBER OF(@c) | @b MEMBER OF(@c) |
+------------------+------------------+
|                1 |                1 |
+------------------+------------------+
1 row in set (0.00 sec)
</pre><p>
          The <code class="literal">MEMBER OF()</code> operator was added in MySQL
          8.0.17.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-modification-functions"></a>12.17.4 Functions That Modify JSON Values</h3>

</div>

</div>

</div>
<p>
      The functions in this section modify JSON values and return the
      result.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_json-array-append"></a><p>
          <a class="indexterm" name="idm46444321296848"></a>

          <a class="link" href="functions.html#function_json-array-append"><code class="literal">JSON_ARRAY_APPEND(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>[,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>] ...)</code></a>
        </p><p>
          Appends values to the end of the indicated arrays within a
          JSON document and returns the result. Returns
          <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or any <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or contains a
          <code class="literal">*</code> or <code class="literal">**</code> wildcard.
        </p><p>
          The path-value pairs are evaluated left to right. The document
          produced by evaluating one pair becomes the new value against
          which the next pair is evaluated.
        </p><p>
          If a path selects a scalar or object value, that value is
          autowrapped within an array and the new value is added to that
          array. Pairs for which the path does not identify any value in
          the JSON document are ignored.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '["a", ["b", "c"], "d"]';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_APPEND(@j, '$[1]', 1);</code></strong>
+----------------------------------+
| JSON_ARRAY_APPEND(@j, '$[1]', 1) |
+----------------------------------+
| ["a", ["b", "c", 1], "d"]        |
+----------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_APPEND(@j, '$[0]', 2);</code></strong>
+----------------------------------+
| JSON_ARRAY_APPEND(@j, '$[0]', 2) |
+----------------------------------+
| [["a", 2], ["b", "c"], "d"]      |
+----------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_APPEND(@j, '$[1][0]', 3);</code></strong>
+-------------------------------------+
| JSON_ARRAY_APPEND(@j, '$[1][0]', 3) |
+-------------------------------------+
| ["a", [["b", 3], "c"], "d"]         |
+-------------------------------------+

mysql&gt; <strong class="userinput"><code>SET @j = '{"a": 1, "b": [2, 3], "c": 4}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_APPEND(@j, '$.b', 'x');</code></strong>
+------------------------------------+
| JSON_ARRAY_APPEND(@j, '$.b', 'x')  |
+------------------------------------+
| {"a": 1, "b": [2, 3, "x"], "c": 4} |
+------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_APPEND(@j, '$.c', 'y');</code></strong>
+--------------------------------------+
| JSON_ARRAY_APPEND(@j, '$.c', 'y')    |
+--------------------------------------+
| {"a": 1, "b": [2, 3], "c": [4, "y"]} |
+--------------------------------------+

mysql&gt; <strong class="userinput"><code>SET @j = '{"a": 1}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_APPEND(@j, '$', 'z');</code></strong>
+---------------------------------+
| JSON_ARRAY_APPEND(@j, '$', 'z') |
+---------------------------------+
| [{"a": 1}, "z"]                 |
+---------------------------------+
</pre><p>
          In MySQL 5.7, this function was named
          <code class="literal">JSON_APPEND()</code>. That name is no longer
          supported in MySQL 8.0.
        </p></li><li class="listitem"><a name="function_json-array-insert"></a><p>
          <a class="indexterm" name="idm46444321269840"></a>

          <a class="link" href="functions.html#function_json-array-insert"><code class="literal">JSON_ARRAY_INSERT(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>[,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>] ...)</code></a>
        </p><p>
          Updates a JSON document, inserting into an array within the
          document and returning the modified document. Returns
          <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or any <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or contains a
          <code class="literal">*</code> or <code class="literal">**</code> wildcard or does
          not end with an array element identifier.
        </p><p>
          The path-value pairs are evaluated left to right. The document
          produced by evaluating one pair becomes the new value against
          which the next pair is evaluated.
        </p><p>
          Pairs for which the path does not identify any array in the
          JSON document are ignored. If a path identifies an array
          element, the corresponding value is inserted at that element
          position, shifting any following values to the right. If a
          path identifies an array position past the end of an array,
          the value is inserted at the end of the array.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '["a", {"b": [1, 2]}, [3, 4]]';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_INSERT(@j, '$[1]', 'x');</code></strong>
+------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[1]', 'x') |
+------------------------------------+
| ["a", "x", {"b": [1, 2]}, [3, 4]]  |
+------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_INSERT(@j, '$[100]', 'x');</code></strong>
+--------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[100]', 'x') |
+--------------------------------------+
| ["a", {"b": [1, 2]}, [3, 4], "x"]    |
+--------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_INSERT(@j, '$[1].b[0]', 'x');</code></strong>
+-----------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[1].b[0]', 'x') |
+-----------------------------------------+
| ["a", {"b": ["x", 1, 2]}, [3, 4]]       |
+-----------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_INSERT(@j, '$[2][1]', 'y');</code></strong>
+---------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[2][1]', 'y') |
+---------------------------------------+
| ["a", {"b": [1, 2]}, [3, "y", 4]]     |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_ARRAY_INSERT(@j, '$[0]', 'x', '$[2][1]', 'y');</code></strong>
+----------------------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[0]', 'x', '$[2][1]', 'y') |
+----------------------------------------------------+
| ["x", "a", {"b": [1, 2]}, [3, 4]]                  |
+----------------------------------------------------+
</pre><p>
          Earlier modifications affect the positions of the following
          elements in the array, so subsequent paths in the same
          <a class="link" href="functions.html#function_json-array-insert"><code class="literal">JSON_ARRAY_INSERT()</code></a> call should
          take this into account. In the final example, the second path
          inserts nothing because the path no longer matches anything
          after the first insert.
        </p></li><li class="listitem"><a name="function_json-insert"></a><p>
          <a class="indexterm" name="idm46444321244272"></a>

          <a class="link" href="functions.html#function_json-insert"><code class="literal">JSON_INSERT(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>[,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>] ...)</code></a>
        </p><p>
          Inserts data into a JSON document and returns the result.
          Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or any <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or contains a
          <code class="literal">*</code> or <code class="literal">**</code> wildcard.
        </p><p>
          The path-value pairs are evaluated left to right. The document
          produced by evaluating one pair becomes the new value against
          which the next pair is evaluated.
        </p><p>
          A path-value pair for an existing path in the document is
          ignored and does not overwrite the existing document value. A
          path-value pair for a nonexisting path in the document adds
          the value to the document if the path identifies one of these
          types of values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              A member not present in an existing object. The member is
              added to the object and associated with the new value.
            </p></li><li class="listitem"><p>
              A position past the end of an existing array. The array is
              extended with the new value. If the existing value is not
              an array, it is autowrapped as an array, then extended
              with the new value.
</p></li></ul>
</div>
<p>
          Otherwise, a path-value pair for a nonexisting path in the
          document is ignored and has no effect.
        </p><p>
          For a comparison of
          <a class="link" href="functions.html#function_json-insert"><code class="literal">JSON_INSERT()</code></a>,
          <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a>, and
          <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a>, see the discussion
          of <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '{ "a": 1, "b": [2, 3]}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]');</code></strong>
+----------------------------------------------------+
| JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]') |
+----------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": "[true, false]"}        |
+----------------------------------------------------+
</pre><p>
          The third and final value listed in the result is a quoted
          string and not an array like the second one (which is not
          quoted in the output); no casting of values to the JSON type
          is performed. To insert the array as an array, you must
          perform such casts explicitly, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_INSERT(@j, '$.a', 10, '$.c', CAST('[true, false]' AS JSON));</code></strong>
+------------------------------------------------------------------+
| JSON_INSERT(@j, '$.a', 10, '$.c', CAST('[true, false]' AS JSON)) |
+------------------------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": [true, false]}                        |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
</pre></li><li class="listitem"><a name="function_json-merge"></a><p>
          <a class="indexterm" name="idm46444321214528"></a>

          <a class="link" href="functions.html#function_json-merge"><code class="literal">JSON_MERGE(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>json_doc</code></em>[,
          <em class="replaceable"><code>json_doc</code></em>] ...)</code></a>
        </p><p>
          Merges two or more JSON documents. Synonym for
          <code class="literal">JSON_MERGE_PRESERVE()</code>; deprecated in MySQL
          8.0.3 and subject to removal in a future release.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE('[1, 2]', '[true, false]');</code></strong>
+---------------------------------------+
| JSON_MERGE('[1, 2]', '[true, false]') |
+---------------------------------------+
| [1, 2, true, false]                   |
+---------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS\G</code></strong>
*************************** 1. row ***************************
  Level: Warning
   Code: 1287
Message: 'JSON_MERGE' is deprecated and will be removed in a future release. \
 Please use JSON_MERGE_PRESERVE/JSON_MERGE_PATCH instead
1 row in set (0.00 sec)
</pre><p>
          For additional examples, see the entry for
          <a class="link" href="functions.html#function_json-merge-preserve"><code class="literal">JSON_MERGE_PRESERVE()</code></a>.
        </p></li><li class="listitem"><a name="function_json-merge-patch"></a><p>
          <a class="indexterm" name="idm46444321198880"></a>

          <a class="link" href="functions.html#function_json-merge-patch"><code class="literal">JSON_MERGE_PATCH(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>json_doc</code></em>[,
          <em class="replaceable"><code>json_doc</code></em>] ...)</code></a>
        </p><p>
          Performs an
          <a class="ulink" href="https://tools.ietf.org/html/rfc7396" target="_top">RFC
          7396</a> compliant merge of two or more JSON documents and
          returns the merged result, without preserving members having
          duplicate keys. Raises an error if at least one of the
          documents passed as arguments to this function is not valid.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            For an explanation and example of the differences between
            this function and <code class="literal">JSON_MERGE_PRESERVE()</code>,
            see
            <a class="xref" href="functions.html#json-merge-patch-json-merge-preserve-compared" title="JSON_MERGE_PATCH() compared with JSON_MERGE_PRESERVE()">JSON_MERGE_PATCH() compared with JSON_MERGE_PRESERVE()</a>.
</p>
</div>
<p>
          <code class="literal">JSON_MERGE_PATCH()</code> performs a merge as
          follows:
</p>
<div class="orderedlist">
<ol class="orderedlist" type="1"><li class="listitem"><p>
              If the first argument is not an object, the result of the
              merge is the same as if an empty object had been merged
              with the second argument.
            </p></li><li class="listitem"><p>
              If the second argument is not an object, the result of the
              merge is the second argument.
            </p></li><li class="listitem"><p>
              If both arguments are objects, the result of the merge is
              an object with the following members:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                  All members of the first object which do not have a
                  corresponding member with the same key in the second
                  object.
                </p></li><li class="listitem"><p>
                  All members of the second object which do not have a
                  corresponding key in the first object, and whose value
                  is not the JSON <code class="literal">null</code> literal.
                </p></li><li class="listitem"><p>
                  All members with a key that exists in both the first
                  and the second object, and whose value in the second
                  object is not the JSON <code class="literal">null</code>
                  literal. The values of these members are the results
                  of recursively merging the value in the first object
                  with the value in the second object.
</p></li></ul>
</div>
</li></ol>
</div>
<p>
          For additional information, see
          <a class="xref" href="data-types.html#json-normalization" title="Normalization, Merging, and Autowrapping of JSON Values">Normalization, Merging, and Autowrapping of JSON Values</a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('[1, 2]', '[true, false]');</code></strong>
+---------------------------------------------+
| JSON_MERGE_PATCH('[1, 2]', '[true, false]') |
+---------------------------------------------+
| [true, false]                               |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('{"name": "x"}', '{"id": 47}');</code></strong>
+-------------------------------------------------+
| JSON_MERGE_PATCH('{"name": "x"}', '{"id": 47}') |
+-------------------------------------------------+
| {"id": 47, "name": "x"}                         |
+-------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('1', 'true');</code></strong>
+-------------------------------+
| JSON_MERGE_PATCH('1', 'true') |
+-------------------------------+
| true                          |
+-------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('[1, 2]', '{"id": 47}');</code></strong>
+------------------------------------------+
| JSON_MERGE_PATCH('[1, 2]', '{"id": 47}') |
+------------------------------------------+
| {"id": 47}                               |
+------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }',</code></strong>
     &gt;     <strong class="userinput"><code>'{ "a": 3, "c":4 }');</code></strong>
+-----------------------------------------------------------+
| JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }') |
+-----------------------------------------------------------+
| {"a": 3, "b": 2, "c": 4}                                  |
+-----------------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }',</code></strong>
     &gt;     <strong class="userinput"><code>'{ "a": 5, "d":6 }');</code></strong>
+-------------------------------------------------------------------------------+
| JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }') |
+-------------------------------------------------------------------------------+
| {"a": 5, "b": 2, "c": 4, "d": 6}                                              |
+-------------------------------------------------------------------------------+
</pre><p>
          You can use this function to remove a member by specifying
          <code class="literal">null</code> as the value of the same member in the
          seond argument, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('{"a":1, "b":2}', '{"b":null}');</code></strong>
+--------------------------------------------------+
| JSON_MERGE_PATCH('{"a":1, "b":2}', '{"b":null}') |
+--------------------------------------------------+
| {"a": 1}                                         |
+--------------------------------------------------+
</pre><p>
          This example shows that the function operates in a recursive
          fashion; that is, values of members are not limited to
          scalars, but rather can themselves be JSON documents:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PATCH('{"a":{"x":1}}', '{"a":{"y":2}}');</code></strong>
+----------------------------------------------------+
| JSON_MERGE_PATCH('{"a":{"x":1}}', '{"a":{"y":2}}') |
+----------------------------------------------------+
| {"a": {"x": 1, "y": 2}}                            |
+----------------------------------------------------+
</pre><p>
          <code class="literal">JSON_MERGE_PATCH()</code> is supported in MySQL
          8.0.3 and later.
        </p><p><a name="json-merge-patch-json-merge-preserve-compared"></a><b>JSON_MERGE_PATCH() compared with JSON_MERGE_PRESERVE(). </b>
            The behavior of <code class="literal">JSON_MERGE_PATCH()</code> is the
            same as that of
            <a class="link" href="functions.html#function_json-merge-preserve"><code class="literal">JSON_MERGE_PRESERVE()</code></a>, with
            the following two exceptions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">JSON_MERGE_PATCH()</code> removes any member
              in the first object with a matching key in the second
              object, provided that the value associated with the key in
              the second object is not JSON <code class="literal">null</code>.
            </p></li><li class="listitem"><p>
              If the second object has a member with a key matching a
              member in the first object,
              <code class="literal">JSON_MERGE_PATCH()</code>
              <span class="emphasis"><em>replaces</em></span> the value in the first
              object with the value in the second object, whereas
              <code class="literal">JSON_MERGE_PRESERVE()</code>
              <span class="emphasis"><em>appends</em></span> the second value to the first
              value.
</p></li></ul>
</div>
<p>
          This example compares the results of merging the same 3 JSON
          objects, each having a matching key <code class="literal">"a"</code>,
          with each of these two functions:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @x = '{ "a": 1, "b": 2 }',</code></strong>
     &gt;     <strong class="userinput"><code>@y = '{ "a": 3, "c": 4 }',</code></strong>
     &gt;     <strong class="userinput"><code>@z = '{ "a": 5, "d": 6 }';</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT  JSON_MERGE_PATCH(@x, @y, @z)    AS Patch,</code></strong>
    -&gt;         <strong class="userinput"><code>JSON_MERGE_PRESERVE(@x, @y, @z) AS Preserve\G</code></strong>
*************************** 1. row ***************************
   Patch: {"a": 5, "b": 2, "c": 4, "d": 6}
Preserve: {"a": [1, 3, 5], "b": 2, "c": 4, "d": 6}
</pre></li><li class="listitem"><a name="function_json-merge-preserve"></a><p>
          <a class="indexterm" name="idm46444321142000"></a>

          <a class="link" href="functions.html#function_json-merge-preserve"><code class="literal">JSON_MERGE_PRESERVE(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>json_doc</code></em>[,
          <em class="replaceable"><code>json_doc</code></em>] ...)</code></a>
        </p><p>
          Merges two or more JSON documents and returns the merged
          result. Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>. An error occurs if any argument is
          not a valid JSON document.
        </p><p>
          Merging takes place according to the following rules. For
          additional information, see
          <a class="xref" href="data-types.html#json-normalization" title="Normalization, Merging, and Autowrapping of JSON Values">Normalization, Merging, and Autowrapping of JSON Values</a>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Adjacent arrays are merged to a single array.
            </p></li><li class="listitem"><p>
              Adjacent objects are merged to a single object.
            </p></li><li class="listitem"><p>
              A scalar value is autowrapped as an array and merged as an
              array.
            </p></li><li class="listitem"><p>
              An adjacent array and object are merged by autowrapping
              the object as an array and merging the two arrays.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PRESERVE('[1, 2]', '[true, false]');</code></strong>
+------------------------------------------------+
| JSON_MERGE_PRESERVE('[1, 2]', '[true, false]') |
+------------------------------------------------+
| [1, 2, true, false]                            |
+------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}');</code></strong>
+----------------------------------------------------+
| JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}') |
+----------------------------------------------------+
| {"id": 47, "name": "x"}                            |
+----------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PRESERVE('1', 'true');</code></strong>
+----------------------------------+
| JSON_MERGE_PRESERVE('1', 'true') |
+----------------------------------+
| [1, true]                        |
+----------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PRESERVE('[1, 2]', '{"id": 47}');</code></strong>
+---------------------------------------------+
| JSON_MERGE_PRESERVE('[1, 2]', '{"id": 47}') |
+---------------------------------------------+
| [1, 2, {"id": 47}]                          |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }',</code></strong>
     &gt;    <strong class="userinput"><code>'{ "a": 3, "c": 4 }');</code></strong>
+--------------------------------------------------------------+
| JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }','{ "a": 3, "c":4 }') |
+--------------------------------------------------------------+
| {"a": [1, 3], "b": 2, "c": 4}                                |
+--------------------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }','{ "a": 3, "c": 4 }',</code></strong>
     &gt;    <strong class="userinput"><code>'{ "a": 5, "d": 6 }');</code></strong>
+----------------------------------------------------------------------------------+
| JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }','{ "a": 3, "c": 4 }','{ "a": 5, "d": 6 }') |
+----------------------------------------------------------------------------------+
| {"a": [1, 3, 5], "b": 2, "c": 4, "d": 6}                                         |
+----------------------------------------------------------------------------------+
</pre><p>
          This function was added in MySQL 8.0.3 as a synonym for
          <a class="link" href="functions.html#function_json-merge"><code class="literal">JSON_MERGE()</code></a>. The
          <code class="literal">JSON_MERGE()</code> function is now deprecated,
          and is subject to removal in a future release of MySQL.
        </p><p>
          This function is similar to but differs from
          <a class="link" href="functions.html#function_json-merge-patch"><code class="literal">JSON_MERGE_PATCH()</code></a> in
          significant respects; see
          <a class="xref" href="functions.html#json-merge-patch-json-merge-preserve-compared" title="JSON_MERGE_PATCH() compared with JSON_MERGE_PRESERVE()">JSON_MERGE_PATCH() compared with JSON_MERGE_PRESERVE()</a>,
          for more information.
        </p></li><li class="listitem"><a name="function_json-remove"></a><p>
          <a class="indexterm" name="idm46444321110480"></a>

          <a class="link" href="functions.html#function_json-remove"><code class="literal">JSON_REMOVE(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>[,
          <em class="replaceable"><code>path</code></em>] ...)</code></a>
        </p><p>
          Removes data from a JSON document and returns the result.
          Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or any <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or is <code class="literal">$</code> or
          contains a <code class="literal">*</code> or <code class="literal">**</code>
          wildcard.
        </p><p>
          The <em class="replaceable"><code>path</code></em> arguments are evaluated
          left to right. The document produced by evaluating one path
          becomes the new value against which the next path is
          evaluated.
        </p><p>
          It is not an error if the element to be removed does not exist
          in the document; in that case, the path does not affect the
          document.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '["a", ["b", "c"], "d"]';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_REMOVE(@j, '$[1]');</code></strong>
+-------------------------+
| JSON_REMOVE(@j, '$[1]') |
+-------------------------+
| ["a", "d"]              |
+-------------------------+
</pre></li><li class="listitem"><a name="function_json-replace"></a><p>
          <a class="indexterm" name="idm46444321091808"></a>

          <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>[,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>] ...)</code></a>
        </p><p>
          Replaces existing values in a JSON document and returns the
          result. Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code>. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or any <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or contains a
          <code class="literal">*</code> or <code class="literal">**</code> wildcard.
        </p><p>
          The path-value pairs are evaluated left to right. The document
          produced by evaluating one pair becomes the new value against
          which the next pair is evaluated.
        </p><p>
          A path-value pair for an existing path in the document
          overwrites the existing document value with the new value. A
          path-value pair for a nonexisting path in the document is
          ignored and has no effect.
        </p><p>
          In MySQL 8.0.4, the optimizer can perform a partial, in-place
          update of a <code class="literal">JSON</code> column instead of removing
          the old document and writing the new document in its entirety
          to the column. This optimization can be performed for an
          update statement that uses the
          <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a> function and
          meets the conditions outlined in
          <a class="xref" href="data-types.html#json-partial-updates" title="Partial Updates of JSON Values">Partial Updates of JSON Values</a>.
        </p><p>
          For a comparison of
          <a class="link" href="functions.html#function_json-insert"><code class="literal">JSON_INSERT()</code></a>,
          <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a>, and
          <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a>, see the discussion
          of <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '{ "a": 1, "b": [2, 3]}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]');</code></strong>
+-----------------------------------------------------+
| JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]') |
+-----------------------------------------------------+
| {"a": 10, "b": [2, 3]}                              |
+-----------------------------------------------------+
</pre></li><li class="listitem"><a name="function_json-set"></a><p>
          <a class="indexterm" name="idm46444321064480"></a>

          <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET(<em class="replaceable"><code>json_doc</code></em>,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>[,
          <em class="replaceable"><code>path</code></em>,
          <em class="replaceable"><code>val</code></em>] ...)</code></a>
        </p><p>
          Inserts or updates data in a JSON document and returns the
          result. Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code> or <em class="replaceable"><code>path</code></em>, if
          given, does not locate an object. An error occurs if the
          <em class="replaceable"><code>json_doc</code></em> argument is not a valid
          JSON document or any <em class="replaceable"><code>path</code></em> argument
          is not a valid path expression or contains a
          <code class="literal">*</code> or <code class="literal">**</code> wildcard.
        </p><p>
          The path-value pairs are evaluated left to right. The document
          produced by evaluating one pair becomes the new value against
          which the next pair is evaluated.
        </p><p>
          A path-value pair for an existing path in the document
          overwrites the existing document value with the new value. A
          path-value pair for a nonexisting path in the document adds
          the value to the document if the path identifies one of these
          types of values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              A member not present in an existing object. The member is
              added to the object and associated with the new value.
            </p></li><li class="listitem"><p>
              A position past the end of an existing array. The array is
              extended with the new value. If the existing value is not
              an array, it is autowrapped as an array, then extended
              with the new value.
</p></li></ul>
</div>
<p>
          Otherwise, a path-value pair for a nonexisting path in the
          document is ignored and has no effect.
        </p><p>
          In MySQL 8.0.4, the optimizer can perform a partial, in-place
          update of a <code class="literal">JSON</code> column instead of removing
          the old document and writing the new document in its entirety
          to the column. This optimization can be performed for an
          update statement that uses the
          <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a> function and meets
          the conditions outlined in
          <a class="xref" href="data-types.html#json-partial-updates" title="Partial Updates of JSON Values">Partial Updates of JSON Values</a>.
        </p><p>
          The <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a>,
          <a class="link" href="functions.html#function_json-insert"><code class="literal">JSON_INSERT()</code></a>, and
          <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a> functions are
          related:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a> replaces
              existing values and adds nonexisting values.
            </p></li><li class="listitem"><p>
              <a class="link" href="functions.html#function_json-insert"><code class="literal">JSON_INSERT()</code></a> inserts
              values without replacing existing values.
            </p></li><li class="listitem"><p>
              <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a> replaces
              <span class="emphasis"><em>only</em></span> existing values.
</p></li></ul>
</div>
<p>
          The following examples illustrate these differences, using one
          path that does exist in the document (<code class="literal">$.a</code>)
          and another that does not exist (<code class="literal">$.c</code>):
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '{ "a": 1, "b": [2, 3]}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_SET(@j, '$.a', 10, '$.c', '[true, false]');</code></strong>
+-------------------------------------------------+
| JSON_SET(@j, '$.a', 10, '$.c', '[true, false]') |
+-------------------------------------------------+
| {"a": 10, "b": [2, 3], "c": "[true, false]"}    |
+-------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]');</code></strong>
+----------------------------------------------------+
| JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]') |
+----------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": "[true, false]"}        |
+----------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]');</code></strong>
+-----------------------------------------------------+
| JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]') |
+-----------------------------------------------------+
| {"a": 10, "b": [2, 3]}                              |
+-----------------------------------------------------+
</pre></li><li class="listitem"><a name="function_json-unquote"></a><p>
          <a class="indexterm" name="idm46444321023328"></a>

          <a class="link" href="functions.html#function_json-unquote"><code class="literal">JSON_UNQUOTE(<em class="replaceable"><code>json_val</code></em>)</code></a>
        </p><p>
          Unquotes JSON value and returns the result as a
          <code class="literal">utf8mb4</code> string. Returns
          <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>. An error occurs if the value starts
          and ends with double quotes but is not a valid JSON string
          literal.
        </p><p>
          Within a string, certain sequences have special meaning unless
          the <a class="link" href="server-administration.html#sqlmode_no_backslash_escapes"><code class="literal">NO_BACKSLASH_ESCAPES</code></a> SQL
          mode is enabled. Each of these sequences begins with a
          backslash (<code class="literal">\</code>), known as the
          <span class="emphasis"><em>escape character</em></span>. MySQL recognizes the
          escape sequences shown in
          <a class="xref" href="functions.html#json-unquote-character-escape-sequences" title="Table 12.22 JSON_UNQUOTE() Special Character Escape Sequences">Table 12.22, “JSON_UNQUOTE() Special Character Escape Sequences”</a>. For
          all other escape sequences, backslash is ignored. That is, the
          escaped character is interpreted as if it was not escaped. For
          example, <code class="literal">\x</code> is just <code class="literal">x</code>.
          These sequences are case-sensitive. For example,
          <code class="literal">\b</code> is interpreted as a backspace, but
          <code class="literal">\B</code> is interpreted as <code class="literal">B</code>.
</p>
<div class="table">
<a name="json-unquote-character-escape-sequences"></a><p class="title"><b>Table 12.22 JSON_UNQUOTE() Special Character Escape Sequences</b></p>
<div class="table-contents">
<table><col width="15%"><col width="85%"><thead><tr>
              <th scope="col">Escape Sequence</th>
              <th scope="col">Character Represented by Sequence</th>
            </tr></thead><tbody><tr>
              <td scope="row"><code class="literal">\"</code><a class="indexterm" name="idm46444321001216"></a><a class="indexterm" name="idm46444321000272"></a></td>
              <td>A double quote (<code class="literal">"</code>) character</td>
            </tr><tr>
              <td scope="row"><code class="literal">\b</code><a class="indexterm" name="idm46444320995856"></a><a class="indexterm" name="idm46444320994912"></a></td>
              <td>A backspace character</td>
            </tr><tr>
              <td scope="row"><code class="literal">\f</code><a class="indexterm" name="idm46444320991136"></a><a class="indexterm" name="idm46444320990192"></a></td>
              <td>A formfeed character</td>
            </tr><tr>
              <td scope="row"><code class="literal">\n</code><a class="indexterm" name="idm46444320986464"></a><a class="indexterm" name="idm46444320985520"></a><a class="indexterm" name="idm46444320984576"></a><a class="indexterm" name="idm46444320983632"></a></td>
              <td>A newline (linefeed) character</td>
            </tr><tr>
              <td scope="row"><code class="literal">\r</code><a class="indexterm" name="idm46444320979888"></a><a class="indexterm" name="idm46444320978944"></a><a class="indexterm" name="idm46444320978000"></a></td>
              <td>A carriage return character</td>
            </tr><tr>
              <td scope="row"><code class="literal">\t</code><a class="indexterm" name="idm46444320974256"></a><a class="indexterm" name="idm46444320973312"></a></td>
              <td>A tab character</td>
            </tr><tr>
              <td scope="row"><code class="literal">\\</code><a class="indexterm" name="idm46444320969584"></a><a class="indexterm" name="idm46444320968640"></a></td>
              <td>A backslash (<code class="literal">\</code>) character</td>
            </tr><tr>
              <td scope="row"><code class="literal">\u<em class="replaceable"><code>XXXX</code></em></code><a class="indexterm" name="idm46444320963936"></a><a class="indexterm" name="idm46444320962992"></a></td>
              <td>UTF-8 bytes for Unicode value <em class="replaceable"><code>XXXX</code></em></td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
          Two simple examples of the use of this function are shown
          here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '"abc"';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @j, JSON_UNQUOTE(@j);</code></strong>
+-------+------------------+
| @j    | JSON_UNQUOTE(@j) |
+-------+------------------+
| "abc" | abc              |
+-------+------------------+
mysql&gt; <strong class="userinput"><code>SET @j = '[1, 2, 3]';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT @j, JSON_UNQUOTE(@j);</code></strong>
+-----------+------------------+
| @j        | JSON_UNQUOTE(@j) |
+-----------+------------------+
| [1, 2, 3] | [1, 2, 3]        |
+-----------+------------------+
</pre><p>
          The following set of examples shows how
          <code class="literal">JSON_UNQUOTE</code> handles escapes with
          <a class="link" href="server-administration.html#sqlmode_no_backslash_escapes"><code class="literal">NO_BACKSLASH_ESCAPES</code></a>
          disabled and enabled:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT @@sql_mode;</code></strong>
+------------+
| @@sql_mode |
+------------+
|            |
+------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_UNQUOTE('"\\t\\u0032"');</code></strong>
+------------------------------+
| JSON_UNQUOTE('"\\t\\u0032"') |
+------------------------------+
|       2                           |
+------------------------------+

mysql&gt; <strong class="userinput"><code>SET @@sql_mode = 'NO_BACKSLASH_ESCAPES';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_UNQUOTE('"\\t\\u0032"');</code></strong>
+------------------------------+
| JSON_UNQUOTE('"\\t\\u0032"') |
+------------------------------+
| \t\u0032                     |
+------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_UNQUOTE('"\t\u0032"');</code></strong>
+----------------------------+
| JSON_UNQUOTE('"\t\u0032"') |
+----------------------------+
|       2                         |
+----------------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-attribute-functions"></a>12.17.5 Functions That Return JSON Value Attributes</h3>

</div>

</div>

</div>
<p>
      The functions in this section return attributes of JSON values.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_json-depth"></a><p>
          <a class="indexterm" name="idm46444320941136"></a>

          <a class="link" href="functions.html#function_json-depth"><code class="literal">JSON_DEPTH(<em class="replaceable"><code>json_doc</code></em>)</code></a>
        </p><p>
          Returns the maximum depth of a JSON document. Returns
          <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>. An error occurs if the argument is
          not a valid JSON document.
        </p><p>
          An empty array, empty object, or scalar value has depth 1. A
          nonempty array containing only elements of depth 1 or nonempty
          object containing only member values of depth 1 has depth 2.
          Otherwise, a JSON document has depth greater than 2.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_DEPTH('{}'), JSON_DEPTH('[]'), JSON_DEPTH('true');</code></strong>
+------------------+------------------+--------------------+
| JSON_DEPTH('{}') | JSON_DEPTH('[]') | JSON_DEPTH('true') |
+------------------+------------------+--------------------+
|                1 |                1 |                  1 |
+------------------+------------------+--------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_DEPTH('[10, 20]'), JSON_DEPTH('[[], {}]');</code></strong>
+------------------------+------------------------+
| JSON_DEPTH('[10, 20]') | JSON_DEPTH('[[], {}]') |
+------------------------+------------------------+
|                      2 |                      2 |
+------------------------+------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_DEPTH('[10, {"a": 20}]');</code></strong>
+-------------------------------+
| JSON_DEPTH('[10, {"a": 20}]') |
+-------------------------------+
|                             3 |
+-------------------------------+
</pre></li><li class="listitem"><a name="function_json-length"></a><p>
          <a class="indexterm" name="idm46444320925424"></a>

          <a class="link" href="functions.html#function_json-length"><code class="literal">JSON_LENGTH(<em class="replaceable"><code>json_doc</code></em>[,
          <em class="replaceable"><code>path</code></em>])</code></a>
        </p><p>
          Returns the length of a JSON document, or, if a
          <em class="replaceable"><code>path</code></em> argument is given, the length
          of the value within the document identified by the path.
          Returns <code class="literal">NULL</code> if any argument is
          <code class="literal">NULL</code> or the <em class="replaceable"><code>path</code></em>
          argument does not identify a value in the document. An error
          occurs if the <em class="replaceable"><code>json_doc</code></em> argument is
          not a valid JSON document or the
          <em class="replaceable"><code>path</code></em> argument is not a valid path
          expression or contains a <code class="literal">*</code> or
          <code class="literal">**</code> wildcard.
        </p><p>
          The length of a document is determined as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The length of a scalar is 1.
            </p></li><li class="listitem"><p>
              The length of an array is the number of array elements.
            </p></li><li class="listitem"><p>
              The length of an object is the number of object members.
            </p></li><li class="listitem"><p>
              The length does not count the length of nested arrays or
              objects.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_LENGTH('[1, 2, {"a": 3}]');</code></strong>
+---------------------------------+
| JSON_LENGTH('[1, 2, {"a": 3}]') |
+---------------------------------+
|                               3 |
+---------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}');</code></strong>
+-----------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}') |
+-----------------------------------------+
|                                       2 |
+-----------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b');</code></strong>
+------------------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b') |
+------------------------------------------------+
|                                              1 |
+------------------------------------------------+
</pre></li><li class="listitem"><a name="function_json-type"></a><p>
          <a class="indexterm" name="idm46444320902544"></a>

          <a class="link" href="functions.html#function_json-type"><code class="literal">JSON_TYPE(<em class="replaceable"><code>json_val</code></em>)</code></a>
        </p><p>
          Returns a <code class="literal">utf8mb4</code> string indicating the
          type of a JSON value. This can be an object, an array, or a
          scalar type, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '{"a": [10, true]}';</code></strong>
mysql&gt; <strong class="userinput"><code>SELECT JSON_TYPE(@j);</code></strong>
+---------------+
| JSON_TYPE(@j) |
+---------------+
| OBJECT        |
+---------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a'));</code></strong>
+------------------------------------+
| JSON_TYPE(JSON_EXTRACT(@j, '$.a')) |
+------------------------------------+
| ARRAY                              |
+------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a[0]'));</code></strong>
+---------------------------------------+
| JSON_TYPE(JSON_EXTRACT(@j, '$.a[0]')) |
+---------------------------------------+
| INTEGER                               |
+---------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a[1]'));</code></strong>
+---------------------------------------+
| JSON_TYPE(JSON_EXTRACT(@j, '$.a[1]')) |
+---------------------------------------+
| BOOLEAN                               |
+---------------------------------------+
</pre><p>
          <a class="link" href="functions.html#function_json-type"><code class="literal">JSON_TYPE()</code></a> returns
          <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_TYPE(NULL);</code></strong>
+-----------------+
| JSON_TYPE(NULL) |
+-----------------+
| NULL            |
+-----------------+
</pre><p>
          An error occurs if the argument is not a valid JSON value:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_TYPE(1);</code></strong>
ERROR 3146 (22032): Invalid data type for JSON data in argument 1
to function json_type; a JSON string or JSON type is required.
</pre><p>
          For a non-<code class="literal">NULL</code>, non-error result, the
          following list describes the possible
          <a class="link" href="functions.html#function_json-type"><code class="literal">JSON_TYPE()</code></a> return values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Purely JSON types:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  <code class="literal">OBJECT</code>: JSON objects
                </p></li><li class="listitem"><p>
                  <code class="literal">ARRAY</code>: JSON arrays
                </p></li><li class="listitem"><p>
                  <code class="literal">BOOLEAN</code>: The JSON true and false
                  literals
                </p></li><li class="listitem"><p>
                  <code class="literal">NULL</code>: The JSON null literal
</p></li></ul>
</div>
</li><li class="listitem"><p>
              Numeric types:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  <code class="literal">INTEGER</code>: MySQL
                  <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">TINYINT</code></a>,
                  <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">SMALLINT</code></a>,
                  <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">MEDIUMINT</code></a> and
                  <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a> and
                  <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> scalars
                </p></li><li class="listitem"><p>
                  <code class="literal">DOUBLE</code>: MySQL
                  <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a>
                  <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a> scalars
                </p></li><li class="listitem"><p>
                  <code class="literal">DECIMAL</code>: MySQL
                  <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> and
                  <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">NUMERIC</code></a> scalars
</p></li></ul>
</div>
</li><li class="listitem"><p>
              Temporal types:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  <code class="literal">DATETIME</code>: MySQL
                  <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATETIME</code></a> and
                  <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a> scalars
                </p></li><li class="listitem"><p>
                  <code class="literal">DATE</code>: MySQL
                  <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">DATE</code></a> scalars
                </p></li><li class="listitem"><p>
                  <code class="literal">TIME</code>: MySQL
                  <a class="link" href="data-types.html#time" title="11.2.3 The TIME Type"><code class="literal">TIME</code></a> scalars
</p></li></ul>
</div>
</li><li class="listitem"><p>
              String types:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  <code class="literal">STRING</code>: MySQL
                  <code class="literal">utf8</code> character type scalars:
                  <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">CHAR</code></a>,
                  <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a>,
                  <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">TEXT</code></a>,
                  <a class="link" href="data-types.html#enum" title="11.3.5 The ENUM Type"><code class="literal">ENUM</code></a>, and
                  <a class="link" href="data-types.html#set" title="11.3.6 The SET Type"><code class="literal">SET</code></a>
</p></li></ul>
</div>
</li><li class="listitem"><p>
              Binary types:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  <code class="literal">BLOB</code>: MySQL binary type scalars
                  including <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
                  <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>,
                  <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a>, and
                  <a class="link" href="data-types.html#bit-type" title="11.1.5 Bit-Value Type - BIT"><code class="literal">BIT</code></a>
</p></li></ul>
</div>
</li><li class="listitem"><p>
              All other types:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  <code class="literal">OPAQUE</code> (raw bits)
</p></li></ul>
</div>
</li></ul>
</div>
</li><li class="listitem"><a name="function_json-valid"></a><p>
          <a class="indexterm" name="idm46444320822656"></a>

          <a class="link" href="functions.html#function_json-valid"><code class="literal">JSON_VALID(<em class="replaceable"><code>val</code></em>)</code></a>
        </p><p>
          Returns 0 or 1 to indicate whether a value is valid JSON.
          Returns <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_VALID('{"a": 1}');</code></strong>
+------------------------+
| JSON_VALID('{"a": 1}') |
+------------------------+
|                      1 |
+------------------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_VALID('hello'), JSON_VALID('"hello"');</code></strong>
+---------------------+-----------------------+
| JSON_VALID('hello') | JSON_VALID('"hello"') |
+---------------------+-----------------------+
|                   0 |                     1 |
+---------------------+-----------------------+
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-table-functions"></a>12.17.6 JSON Table Functions</h3>

</div>

</div>

</div>
<p>
      This section contains information about JSON functions that
      convert JSON data to tabular data. In MySQL 8.0.4 and later, one
      such function—<code class="literal">JSON_TABLE()</code>—is
      supported.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_json-table"></a><p>
          <a class="indexterm" name="idm46444320806032"></a>

          <a class="link" href="functions.html#function_json-table"><code class="literal">JSON_TABLE(<em class="replaceable"><code>expr</code></em>,
          <em class="replaceable"><code>path</code></em> COLUMNS
          (<em class="replaceable"><code>column_list</code></em>) [AS]
          <em class="replaceable"><code>alias</code></em>)</code></a>
        </p><p>
          Extracts data from a JSON document and returns it as a
          relational table having the specified columns. The complete
          syntax for this function is shown here:
        </p><pre data-lang="clike" class="programlisting">JSON_TABLE(
    <em class="replaceable"><code>expr</code></em>,
    <em class="replaceable"><code>path</code></em> COLUMNS (<em class="replaceable"><code>column_list</code></em>)
)   [AS] <em class="replaceable"><code>alias</code></em>

<em class="replaceable"><code>column_list</code></em>:
    <em class="replaceable"><code>column</code></em>[, <em class="replaceable"><code>column</code></em>][, ...]

<em class="replaceable"><code>column</code></em>:
    <em class="replaceable"><code>name</code></em> FOR ORDINALITY
    |  <em class="replaceable"><code>name</code></em> <em class="replaceable"><code>type</code></em> PATH <em class="replaceable"><code>string path</code></em> [<em class="replaceable"><code>on_empty</code></em>] [<em class="replaceable"><code>on_error</code></em>]
    |  <em class="replaceable"><code>name</code></em> <em class="replaceable"><code>type</code></em> EXISTS PATH <em class="replaceable"><code>string path</code></em>
    |  NESTED [PATH] <em class="replaceable"><code>path</code></em> COLUMNS (<em class="replaceable"><code>column_list</code></em>)

<em class="replaceable"><code>on_empty</code></em>:
    {NULL | DEFAULT | ERROR <em class="replaceable"><code>json_string</code></em>} ON EMPTY

<em class="replaceable"><code>on_error</code></em>:
    {NULL | DEFAULT | ERROR <em class="replaceable"><code>json_string</code></em>} ON ERROR
</pre><p>
          <em class="replaceable"><code>expr</code></em>: This is an expression that
          returns JSON data. This can be a constant
          (<code class="literal">'{"a":1}'</code>), a column
          (<code class="literal">t1.json_data</code>, given table
          <code class="literal">t1</code> specified prior to
          <code class="literal">JSON_TABLE()</code> in the <code class="literal">FROM</code>
          clause), or a function call
          (<code class="literal">JSON_EXTRACT(t1.json_data,'$.post.comments')</code>).
        </p><p>
          <em class="replaceable"><code>path</code></em>: A JSON path expression, which
          is applied to the data source. We refer to the JSON value
          matching the path as the <span class="emphasis"><em>row source</em></span>; this
          is used to generate a row of relational data. The
          <code class="literal">COLUMNS</code> clause evaluates the row source,
          finds specific JSON values within the row source, and returns
          those JSON values as SQL values in individual columns of a row
          of relational data.
        </p><p>
          The <em class="replaceable"><code>alias</code></em> is required. The usual
          rules for table aliases apply (see
          <a class="xref" href="language-structure.html#identifiers" title="9.2 Schema Object Names">Section 9.2, “Schema Object Names”</a>).
        </p><p>
          <code class="literal">JSON_TABLE()</code> supports four types of
          columns, described in the following list:
</p>
<div class="orderedlist">
<ol class="orderedlist" type="1"><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>name</code></em> FOR
              ORDINALITY</code>: This type enumerates rows in the
              <code class="literal">COLUMNS</code> clause; the column named
              <em class="replaceable"><code>name</code></em> is a counter whose type is
              <code class="literal">UNSIGNED INT</code>, and whose initial value
              is 1. This is equivalent to specifying a column as
              <code class="literal">AUTO_INCREMENT</code> in a
              <a class="link" href="sql-statements.html#create-table" title="13.1.20 CREATE TABLE Statement"><code class="literal">CREATE TABLE</code></a> statement, and
              can be used to distinguish parent rows with the same value
              for multiple rows generated by a <code class="literal">NESTED
              [PATH]</code> clause.
            </p></li><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>name</code></em>
              <em class="replaceable"><code>type</code></em> PATH
              <em class="replaceable"><code>string_path</code></em>
              [<em class="replaceable"><code>on_empty</code></em>]
              [<em class="replaceable"><code>on_error</code></em>]</code>: Columns
              of this type are used to extract values specified by
              <em class="replaceable"><code>string_path</code></em>.
              <em class="replaceable"><code>type</code></em> is a MySQL scalar data
              type (that is, it cannot be an object or array).
              <code class="literal">JSON_TABLE()</code> extracts data as JSON then
              coerces it to the column type, using the regular automatic
              type conversion applying to JSON data in MySQL. A missing
              value triggers the <em class="replaceable"><code>on_empty</code></em>
              clause. Saving an object or array triggers the optional
              <em class="replaceable"><code>on error</code></em> clause; this also
              occurs when an error takes place during coercion from the
              value saved as JSON to the table column, such as trying to
              save the string <code class="literal">'asd'</code> to an integer
              column.
            </p></li><li class="listitem"><p>
              <code class="literal"><em class="replaceable"><code>name</code></em>
              <em class="replaceable"><code>type</code></em> EXISTS PATH
              <em class="replaceable"><code>path</code></em></code>: This column
              returns 1 if any data is present at the location specified
              by <em class="replaceable"><code>path</code></em>, and 0 otherwise.
              <em class="replaceable"><code>type</code></em> can be any valid MySQL
              data type, but should normally be specified as some
              variety of <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a>.
            </p></li><li class="listitem"><p>
              <code class="literal">NESTED [PATH] <em class="replaceable"><code>path</code></em>
              COLUMNS
              (<em class="replaceable"><code>column_list</code></em>)</code>: This
              flattens nested objects or arrays in JSON data into a
              single row along with the JSON values from the parent
              object or array. Using multiple <code class="literal">PATH</code>
              options allows projection of JSON values from multiple
              levels of nesting into a single row.
            </p><p>
              The <em class="replaceable"><code>path</code></em> is relative to the
              parent path row path of <code class="literal">JSON_TABLE()</code>,
              or the path of the parent <code class="literal">NESTED [PATH]</code>
              clause in the event of nested paths.
</p></li></ol>
</div>
<p>
          <em class="replaceable"><code>on empty</code></em>, if specified, determines
          what <code class="literal">JSON_TABLE()</code> does in the event that
          data is missing (depending on type). This clause is also
          triggered on a column in a <code class="literal">NESTED PATH</code>
          clause when the latter has no match and a
          <code class="literal">NULL</code> complemented row is produced for it.
          <em class="replaceable"><code>on empty</code></em> takes one of the following
          values:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">NULL ON EMPTY</code>: The column is set to
              <code class="literal">NULL</code>; this is the default behavior.
            </p></li><li class="listitem"><p>
              <code class="literal">DEFAULT <em class="replaceable"><code>json_string</code></em> ON
              EMPTY</code>: the provided
              <em class="replaceable"><code>json_string</code></em> is parsed as JSON,
              as long as it is valid, and stored instead of the missing
              value. Column type rules also apply to the default value.
            </p></li><li class="listitem"><p>
              <code class="literal">ERROR ON EMPTY</code>: An error is thrown.
</p></li></ul>
</div>
<p>
          If used, <em class="replaceable"><code>on_error</code></em> takes one of the
          following values with the corresponding result as shown here:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">NULL ON ERROR</code>: The column is set to
              <code class="literal">NULL</code>; this is the default behavior.
            </p></li><li class="listitem"><p>
              <code class="literal">DEFAULT <em class="replaceable"><code>json string</code></em> ON
              ERROR</code>: The
              <em class="replaceable"><code>json_string</code></em> is parsed as JSON
              (provided that it is valid) and stored instead of the
              object or array.
            </p></li><li class="listitem"><p>
              <code class="literal">ERROR ON ERROR</code>: An error is thrown.
</p></li></ul>
</div>
<p>
          Prior to MySQL 8.0.20, a warning was thrown if a type
          conversion error occurred with <code class="literal">NULL ON
          ERROR</code> or <code class="literal">DEFAULT ... ON ERROR</code> was
          specified or implied. In MySQL 8.0.20 and later, this is no
          longer the case. (Bug #30628330)
        </p><p>
          Previously, it was possible to specify <code class="literal">ON
          EMPTY</code> and <code class="literal">ON ERROR</code> clauses in
          either order. This runs counter to the SQL standard, which
          stipulates that <code class="literal">ON EMPTY</code>, if specified,
          must precede any <code class="literal">ON ERROR</code> clause. For this
          reason, beginning with MySQL 8.0.20, specifying <code class="literal">ON
          ERROR</code> before <code class="literal">ON EMPTY</code> is
          deprecated; trying to do so causes the server to issue a
          warning. Support for the nonstandard syntax will be removed in
          a future version of MySQL.
        </p><p>
          When a value saved to a column is truncated, such as saving
          3.14159 in a <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL(10,1)</code></a>
          column, a warning is issued independently of any <code class="literal">ON
          ERROR</code> option. When multiple values are truncated in
          a single statement, the warning is issued only once.
        </p><p>
          The following query demonstrates the use of <code class="literal">ON
          EMPTY</code> and <code class="literal">ON ERROR</code>. The row
          corresponding to <code class="literal">{"b":1}</code> is empty for the
          path <code class="literal">"$.a"</code>, and attempting to save
          <code class="literal">[1,2]</code> as a scalar produces an error; these
          rows are highlighted in the output shown.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT *</code></strong>
    -&gt; <strong class="userinput"><code>FROM</code></strong>
    -&gt;   <strong class="userinput"><code>JSON_TABLE(</code></strong>
    -&gt;     <strong class="userinput"><code>'[{"a":"3"},{"a":2},{"b":1},{"a":0},{"a":[1,2]}]',</code></strong>
    -&gt;     <strong class="userinput"><code>"$[*]"</code></strong>
    -&gt;     <strong class="userinput"><code>COLUMNS(</code></strong>
    -&gt;       <strong class="userinput"><code>rowid FOR ORDINALITY,</code></strong>
    -&gt;       <strong class="userinput"><code>ac VARCHAR(100) PATH "$.a" DEFAULT '111' ON EMPTY DEFAULT '999' ON ERROR,</code></strong>
    -&gt;       <strong class="userinput"><code>aj JSON PATH "$.a" DEFAULT '{"x": 333}' ON EMPTY,</code></strong>
    -&gt;       <strong class="userinput"><code>bx INT EXISTS PATH "$.b"</code></strong>
    -&gt;     <strong class="userinput"><code>)</code></strong>
    -&gt;   <strong class="userinput"><code>) AS tt;</code></strong>

+-------+------+------------+------+
| rowid | ac   | aj         | bx   |
+-------+------+------------+------+
|     1 | 3    | "3"        |    0 |
|     2 | 2    | 2          |    0 |
<span class="emphasis"><em>|     3 | 111  | {"x": 333} |    1 |</em></span>
|     4 | 0    | 0          |    0 |
<span class="emphasis"><em>|     5 | 999  | [1, 2]     |    0 |</em></span>
+-------+------+------------+------+
5 rows in set (0.00 sec)
</pre><p>
          Column names are subject to the usual rules and limitations
          governing table column names. See
          <a class="xref" href="language-structure.html#identifiers" title="9.2 Schema Object Names">Section 9.2, “Schema Object Names”</a>.
        </p><p>
          All JSON and JSON path expressions are checked for validity;
          an invalid expression of either type causes an error.
        </p><p>
          Each match for the <em class="replaceable"><code>path</code></em> preceding
          the <code class="literal">COLUMNS</code> keyword maps to an individual
          row in the result table. For example, the following query
          gives the result shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT *</code></strong>
    -&gt; <strong class="userinput"><code>FROM</code></strong>
    -&gt;   <strong class="userinput"><code>JSON_TABLE(</code></strong>
    -&gt;     <strong class="userinput"><code>'[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]',</code></strong>
    -&gt;     <strong class="userinput"><code>"$[*]" COLUMNS(</code></strong>
    -&gt;       <strong class="userinput"><code>xval VARCHAR(100) PATH "$.x",</code></strong>
    -&gt;       <strong class="userinput"><code>yval VARCHAR(100) PATH "$.y"</code></strong>
    -&gt;     <strong class="userinput"><code>)</code></strong>
    -&gt;   <strong class="userinput"><code>) AS  jt1;</code></strong>

+------+------+
| xval | yval |
+------+------+
| 2    | 8    |
| 3    | 7    |
| 4    | 6    |
+------+------+
</pre><p>
          The expression <code class="literal">"$[*]"</code> matches each element
          of the array. You can filter the rows in the result by
          modifying the path. For example, using
          <code class="literal">"$[1]"</code> limits extraction to the second
          element of the JSON array used as the source, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT *</code></strong>
    -&gt; <strong class="userinput"><code>FROM</code></strong>
    -&gt;   <strong class="userinput"><code>JSON_TABLE(</code></strong>
    -&gt;     <strong class="userinput"><code>'[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]',</code></strong>
    -&gt;     <strong class="userinput"><code>"$[1]" COLUMNS(</code></strong>
    -&gt;       <strong class="userinput"><code>xval VARCHAR(100) PATH "$.x",</code></strong>
    -&gt;       <strong class="userinput"><code>yval VARCHAR(100) PATH "$.y"</code></strong>
    -&gt;     <strong class="userinput"><code>)</code></strong>
    -&gt;   <strong class="userinput"><code>) AS  jt1;</code></strong>

+------+------+
| xval | yval |
+------+------+
| 3    | 7    |
+------+------+
</pre><p>
          Within a column definition, <code class="literal">"$"</code> passes the
          entire match to the column; <code class="literal">"$.x"</code> and
          <code class="literal">"$.y"</code> pass only the values corresponding to
          the keys <code class="literal">x</code> and <code class="literal">y</code>,
          respectively, within that match. For more information, see
          <a class="xref" href="data-types.html#json-path-syntax" title="JSON Path Syntax">JSON Path Syntax</a>.
        </p><p>
          <code class="literal">NESTED PATH</code> (or simply
          <code class="literal">NESTED</code>; <code class="literal">PATH</code> is
          optional) produces a set of records for each match in the
          <code class="literal">COLUMNS</code> clause to which it belongs. If
          there is no match, all columns of the nested path are set to
          <code class="literal">NULL</code>. This implements an outer join between
          the topmost clause and <code class="literal">NESTED [PATH]</code>. An
          inner join can be emulated by applying a suitable condition in
          the <code class="literal">WHERE</code> clause, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT *</code></strong>
    -&gt; <strong class="userinput"><code>FROM</code></strong>
    -&gt;   <strong class="userinput"><code>JSON_TABLE(</code></strong>
    -&gt;     <strong class="userinput"><code>'[ {"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}, {"a":3}]',</code></strong>
    -&gt;     <strong class="userinput"><code>'$[*]' COLUMNS(</code></strong>
    -&gt;             <strong class="userinput"><code>a INT PATH '$.a',</code></strong>
    -&gt;             <strong class="userinput"><code>NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$')</code></strong>
    -&gt;            <strong class="userinput"><code>)</code></strong>
    -&gt;    <strong class="userinput"><code>) AS jt</code></strong>
    -&gt; <strong class="userinput"><code>WHERE b IS NOT NULL;</code></strong>

+------+------+
| a    | b    |
+------+------+
|    1 |   11 |
|    1 |  111 |
|    2 |   22 |
|    2 |  222 |
+------+------+
</pre><p>
          Sibling nested paths—that is, two or more instances of
          <code class="literal">NESTED [PATH]</code> in the same
          <code class="literal">COLUMNS</code> clause—are processed one
          after another, one at a time. While one nested path is
          producing records, columns of any sibling nested path
          expressions are set to <code class="literal">NULL</code>. This means
          that the total number of records for a single match within a
          single containing <code class="literal">COLUMNS</code> clause is the sum
          and not the product of all records produced by <code class="literal">NESTED
          [PATH]</code> modifiers, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT *</code></strong>
    -&gt; <strong class="userinput"><code>FROM</code></strong>
    -&gt;   <strong class="userinput"><code>JSON_TABLE(</code></strong>
    -&gt;     <strong class="userinput"><code>'[{"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}]',</code></strong>
    -&gt;     <strong class="userinput"><code>'$[*]' COLUMNS(</code></strong>
    -&gt;         <strong class="userinput"><code>a INT PATH '$.a',</code></strong>
    -&gt;         <strong class="userinput"><code>NESTED PATH '$.b[*]' COLUMNS (b1 INT PATH '$'),</code></strong>
    -&gt;         <strong class="userinput"><code>NESTED PATH '$.b[*]' COLUMNS (b2 INT PATH '$')</code></strong>
    -&gt;     <strong class="userinput"><code>)</code></strong>
    -&gt; <strong class="userinput"><code>) AS jt;</code></strong>

+------+------+------+
| a    | b1   | b2   |
+------+------+------+
|    1 |   11 | NULL |
|    1 |  111 | NULL |
|    1 | NULL |   11 |
|    1 | NULL |  111 |
|    2 |   22 | NULL |
|    2 |  222 | NULL |
|    2 | NULL |   22 |
|    2 | NULL |  222 |
+------+------+------+
</pre><p>
          A <code class="literal">FOR ORDINALITY</code> column enumerates records
          produced by the <code class="literal">COLUMNS</code> clause, and can be
          used to distinguish parent records of a nested path,
          especially if values in parent records are the same, as can be
          seen here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT *</code></strong>
    -&gt; <strong class="userinput"><code>FROM</code></strong>
    -&gt;   <strong class="userinput"><code>JSON_TABLE(</code></strong>
    -&gt;     <strong class="userinput"><code>'[{"a": "a_val",</code></strong>
    '&gt;       <strong class="userinput"><code>"b": [{"c": "c_val", "l": [1,2]}]},</code></strong>
    '&gt;     <strong class="userinput"><code>{"a": "a_val",</code></strong>
    '&gt;       <strong class="userinput"><code>"b": [{"c": "c_val","l": [11]}, {"c": "c_val", "l": [22]}]}]',</code></strong>
    -&gt;     <strong class="userinput"><code>'$[*]' COLUMNS(</code></strong>
    -&gt;       <strong class="userinput"><code>top_ord FOR ORDINALITY,</code></strong>
    -&gt;       <strong class="userinput"><code>apath VARCHAR(10) PATH '$.a',</code></strong>
    -&gt;       <strong class="userinput"><code>NESTED PATH '$.b[*]' COLUMNS (</code></strong>
    -&gt;         <strong class="userinput"><code>bpath VARCHAR(10) PATH '$.c',</code></strong>
    -&gt;         <strong class="userinput"><code>ord FOR ORDINALITY,</code></strong>
    -&gt;         <strong class="userinput"><code>NESTED PATH '$.l[*]' COLUMNS (lpath varchar(10) PATH '$')</code></strong>
    -&gt;         <strong class="userinput"><code>)</code></strong>
    -&gt;     <strong class="userinput"><code>)</code></strong>
    -&gt; <strong class="userinput"><code>) as jt;</code></strong>

+---------+---------+---------+------+-------+
| top_ord | apath   | bpath   | ord  | lpath |
+---------+---------+---------+------+-------+
|       1 |  a_val  |  c_val  |    1 | 1     |
|       1 |  a_val  |  c_val  |    1 | 2     |
|       2 |  a_val  |  c_val  |    1 | 11    |
|       2 |  a_val  |  c_val  |    2 | 22    |
+---------+---------+---------+------+-------+
</pre><p>
          The source document contains an array of two elements; each of
          these elements produces two rows. The values of
          <code class="literal">apath</code> and <code class="literal">bpath</code> are the
          same over the entire result set; this means that they cannot
          be used to determine whether <code class="literal">lpath</code> values
          came from the same or different parents. The value of the
          <code class="literal">ord</code> column remains the same as the set of
          records having <code class="literal">top_ord</code> equal to 1, so these
          two values are from a single object. The remaining two values
          are from different objects, since they have different values
          in the <code class="literal">ord</code> column.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-validation-functions"></a>12.17.7 JSON Schema Validation Functions</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444320634416"></a><p>
      Beginning with MySQL 8.0.17, MySQL supports validation of JSON
      documents against JSON schemas conforming to
      <a class="ulink" href="https://json-schema.org/specification-links.html#draft-4" target="_top">Draft
      4 of the JSON Schema specification</a>. This can be done using
      either of the functions detailed in this section, both of which
      take two orguments, a JSON schema, and a JSON document which is
      validated against the schema.
      <a class="link" href="functions.html#function_json-schema-valid"><code class="literal">JSON_SCHEMA_VALID()</code></a> returns true if
      the document is validates against the schema, and false if it is
      not;
      <a class="link" href="functions.html#function_json-schema-validation-report"><code class="literal">JSON_SCHEMA_VALIDATION_REPORT()</code></a>
      provides a report in JSON format on the validation.
    </p><p>
      Both functions handle null or invalid input as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If at least one of the arguments is <code class="literal">NULL</code>,
          the function returns <code class="literal">NULL</code>.
        </p></li><li class="listitem"><p>
          If at least one of the arguments is not valid JSON, the
          function raises an error
          (<a class="link" href="error-handling.html#error_er_invalid_type_for_json"><code class="literal">ER_INVALID_TYPE_FOR_JSON</code></a>)
        </p></li><li class="listitem"><p>
          In addition, if the schema is not a valid JSON object, the
          function returns
          <a class="link" href="error-handling.html#error_er_invalid_json_type"><code class="literal">ER_INVALID_JSON_TYPE</code></a>.
</p></li></ul>
</div>
<p>
      MySQL supports the <code class="literal">required</code> attribute in JSON
      schemas to enforce the inclusion of required properties (see the
      examples in the function descriptions).
    </p><p>
      MySQL supports the <code class="literal">id</code>,
      <code class="literal">$schema</code>, <code class="literal">description</code>, and
      <code class="literal">type</code> attributes in JSON schemas but does not
      require any of these.
    </p><p>
      MySQL does not support external resources in JSON schemas; using
      the <code class="literal">$ref</code> keyword causes
      <code class="literal">JSON_SCHEMA_VALID()</code> to fail with
      <a class="link" href="error-handling.html#error_er_not_supported_yet"><code class="literal">ER_NOT_SUPPORTED_YET</code></a>.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
        MySQL supports regular expression patterns in JSON schema, which
        supports but silently ignores invalid patterns (see the
        description of <code class="literal">JSON_SCHEMA_VALID()</code> for an
        example).
</p>
</div>
<p>
      These functions are described in detail in the following list:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_json-schema-valid"></a><p>
          <a class="indexterm" name="idm46444320608112"></a>

          <a class="link" href="functions.html#function_json-schema-valid"><code class="literal">JSON_SCHEMA_VALID(<em class="replaceable"><code>schema</code></em>,<em class="replaceable"><code>document</code></em>)</code></a>
        </p><p>
          Validates a JSON <em class="replaceable"><code>document</code></em> against a
          JSON <em class="replaceable"><code>schema</code></em>. Both
          <em class="replaceable"><code>schema</code></em> and
          <em class="replaceable"><code>document</code></em> are required. The schema
          must be a valid JSON object; the document must be a valid JSON
          document. Provided that these conditions are met: If the
          document validates against the schema, the function returns
          true (1); otherwise, it returns false (0).
        </p><p>
          In this example, we set a user variable
          <code class="literal">@schema</code> to the value of a a JSON schema for
          geographical coordinates, and another one
          <code class="literal">@document</code> to the value of a JSON document
          containing one such coordinate. We then verify that
          <code class="literal">@document</code> validates according to
          <code class="literal">@schema</code> by using them as the arguments to
          <code class="literal">JSON_SCHEMA_VALID()</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @schema = '{</code></strong>
    '&gt;  <strong class="userinput"><code>"id": "http://json-schema.org/geo",</code></strong>
    '&gt; <strong class="userinput"><code>"$schema": "http://json-schema.org/draft-04/schema#",</code></strong>
    '&gt; <strong class="userinput"><code>"description": "A geographical coordinate",</code></strong>
    '&gt; <strong class="userinput"><code>"type": "object",</code></strong>
    '&gt; <strong class="userinput"><code>"properties": {</code></strong>
    '&gt;   <strong class="userinput"><code>"latitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -90,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 90</code></strong>
    '&gt;   <strong class="userinput"><code>},</code></strong>
    '&gt;   <strong class="userinput"><code>"longitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -180,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 180</code></strong>
    '&gt;   <strong class="userinput"><code>}</code></strong>
    '&gt; <strong class="userinput"><code>},</code></strong>
    '&gt; <strong class="userinput"><code>"required": ["latitude", "longitude"]</code></strong>
    '&gt;<strong class="userinput"><code>}';</code></strong>
Query OK, 0 rows affected (0.01 sec)

mysql&gt; <strong class="userinput"><code>SET @document = '{</code></strong>
    '&gt; <strong class="userinput"><code>"latitude": 63.444697,</code></strong>
    '&gt; <strong class="userinput"><code>"longitude": 10.445118</code></strong>
    '&gt;<strong class="userinput"><code>}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_SCHEMA_VALID(@schema, @document);</code></strong>
+---------------------------------------+
| JSON_SCHEMA_VALID(@schema, @document) |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          Since <code class="literal">@schema</code> contains the
          <code class="literal">required</code> attribute, we can set
          <code class="literal">@document</code> to a value that is otherwise
          valid but does not contain the required properties, then test
          it against <code class="literal">@schema</code>, like this:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @document = '{}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_SCHEMA_VALID(@schema, @document);</code></strong>
+---------------------------------------+
| JSON_SCHEMA_VALID(@schema, @document) |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          If we now set the value of <code class="literal">@schema</code> to the
          same JSON schema but without the <code class="literal">required</code>
          attribute, <code class="literal">@document</code> validates because it
          is a valid JSON object, even though it contains no properties,
          as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @schema = '{</code></strong>
    '&gt; <strong class="userinput"><code>"id": "http://json-schema.org/geo",</code></strong>
    '&gt; <strong class="userinput"><code>"$schema": "http://json-schema.org/draft-04/schema#",</code></strong>
    '&gt; <strong class="userinput"><code>"description": "A geographical coordinate",</code></strong>
    '&gt; <strong class="userinput"><code>"type": "object",</code></strong>
    '&gt; <strong class="userinput"><code>"properties": {</code></strong>
    '&gt;   <strong class="userinput"><code>"latitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -90,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 90</code></strong>
    '&gt;   <strong class="userinput"><code>},</code></strong>
    '&gt;   <strong class="userinput"><code>"longitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -180,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 180</code></strong>
    '&gt;   <strong class="userinput"><code>}</code></strong>
    '&gt; <strong class="userinput"><code>}</code></strong>
    '&gt;<strong class="userinput"><code>}';</code></strong>
Query OK, 0 rows affected (0.00 sec)


mysql&gt; <strong class="userinput"><code>SELECT JSON_SCHEMA_VALID(@schema, @document);</code></strong>
+---------------------------------------+
| JSON_SCHEMA_VALID(@schema, @document) |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
1 row in set (0.00 sec)
</pre><a class="indexterm" name="idm46444320554544"></a><a class="indexterm" name="idm46444320553040"></a><p><a name="json-validation-functions-constraints"></a><b>JSON_SCHEMA_VALID() and CHECK constraints. </b>
            <code class="literal">JSON_SCHEMA_VALID()</code> can also be used to
            enforce <code class="literal">CHECK</code> constraints.
          </p><p>
          Consider the table <code class="literal">geo</code> created as shown
          here, with a JSON column <code class="literal">coordinate</code>
          representing a point of latitude and longitude on a map,
          governed by the JSON schema used as an argument in a
          <code class="literal">JSON_SCHEMA_VALID()</code> call which is passed as
          the expression for a <code class="literal">CHECK</code> constraint on
          this table:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE geo (</code></strong>
    -&gt;     <strong class="userinput"><code>coordinate JSON,</code></strong>
    -&gt;     <strong class="userinput"><code>CHECK(</code></strong>
    -&gt;         <strong class="userinput"><code>JSON_SCHEMA_VALID(</code></strong>
    -&gt;             <strong class="userinput"><code>'{</code></strong>
    '&gt;                 <strong class="userinput"><code>"type":"object",</code></strong>
    '&gt;                 <strong class="userinput"><code>"properties":{</code></strong>
    '&gt;                       <strong class="userinput"><code>"latitude":{"type":"number", "minimum":-90, "maximum":90},</code></strong>
    '&gt;                       <strong class="userinput"><code>"longitude":{"type":"number", "minimum":-180, "maximum":180}</code></strong>
    '&gt;                 <strong class="userinput"><code>},</code></strong>
    '&gt;                 <strong class="userinput"><code>"required": ["latitude", "longitude"]</code></strong>
    '&gt;             <strong class="userinput"><code>}',</code></strong>
    -&gt;             <strong class="userinput"><code>coordinate</code></strong>
    -&gt;         <strong class="userinput"><code>)</code></strong>
    -&gt;     <strong class="userinput"><code>)</code></strong>
    -&gt; <strong class="userinput"><code>);</code></strong>
Query OK, 0 rows affected (0.45 sec)
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            Because a MySQL <code class="literal">CHECK</code> constraint cannot
            contain references to variables, you must pass the JSON
            schema to <code class="literal">JSON_SCHEMA_VALID()</code> inline when
            using it to specify such a constraint for a table.
</p>
</div>
<p>
          We assign JSON values representing coordinates to three
          variables, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @point1 = '{"latitude":59, "longitude":18}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @point2 = '{"latitude":91, "longitude":0}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @point3 = '{"longitude":120}';</code></strong>
Query OK, 0 rows affected (0.00 sec)
</pre><p>
          The first of these values is valid, as can be seen in the
          following <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> statement:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; INSERT INTO geo VALUES(@point1);
Query OK, 1 row affected (0.05 sec)</pre><p>
          The second JSON value is invalid and so fails the constraint,
          as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; INSERT INTO geo VALUES(@point2);
ERROR 3819 (HY000): Check constraint 'geo_chk_1' is violated.</pre><p>
          In MySQL 8.0.19 and later, you can obtain precise information
          about the nature of the failure—in this case, that the
          <code class="literal">latitude</code> value exceeds the maximum defined
          in the schema—by issuing a <a class="link" href="sql-statements.html#show-warnings" title="13.7.7.40 SHOW WARNINGS Statement"><code class="literal">SHOW
          WARNINGS</code></a> statement:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SHOW WARNINGS\G</code></strong>
*************************** 1. row ***************************
  Level: Error
   Code: 3934
Message: The JSON document location '#/latitude' failed requirement 'maximum' at
JSON Schema location '#/properties/latitude'.
*************************** 2. row ***************************
  Level: Error
   Code: 3819
Message: Check constraint 'geo_chk_1' is violated.
2 rows in set (0.00 sec)
</pre><p>
          The third coordinate value defined above is also invalid,
          since it is missing the required <code class="literal">latitude</code>
          property. As before, you can see this by attempting to insert
          the value into the <code class="literal">geo</code> table, then issuing
          <code class="literal">SHOW WARNINGS</code> afterwards:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>INSERT INTO geo VALUES(@point3);</code></strong>
ERROR 3819 (HY000): Check constraint 'geo_chk_1' is violated.
mysql&gt; <strong class="userinput"><code>SHOW WARNINGS\G</code></strong>
*************************** 1. row ***************************
  Level: Error
   Code: 3934
Message: The JSON document location '#' failed requirement 'required' at JSON
Schema location '#'.
*************************** 2. row ***************************
  Level: Error
   Code: 3819
Message: Check constraint 'geo_chk_1' is violated.
2 rows in set (0.00 sec)
</pre><p>
          See <a class="xref" href="sql-statements.html#create-table-check-constraints" title="13.1.20.6 CHECK Constraints">Section 13.1.20.6, “CHECK Constraints”</a>, for more
          information.
        </p><a class="indexterm" name="idm46444320509600"></a><p>
          JSON Schema has support for specifying regular expression
          patterns for strings, but the implementation used by MySQL
          silently ignores invalid patterns. This means that
          <code class="literal">JSON_SCHEMA_VALID()</code> can return true even
          when a regular expression pattern is invalid, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', '"abc"');</code></strong>
+---------------------------------------------------------------+
| JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', '"abc"') |
+---------------------------------------------------------------+
|                                                             1 |
+---------------------------------------------------------------+
1 row in set (0.04 sec)
</pre></li><li class="listitem"><a name="function_json-schema-validation-report"></a><p>
          <a class="indexterm" name="idm46444320501024"></a>

          <a class="link" href="functions.html#function_json-schema-validation-report"><code class="literal">JSON_SCHEMA_VALIDATION_REPORT(<em class="replaceable"><code>schema</code></em>,<em class="replaceable"><code>document</code></em>)</code></a>
        </p><p>
          Validates a JSON <em class="replaceable"><code>document</code></em> against a
          JSON <em class="replaceable"><code>schema</code></em>. Both
          <em class="replaceable"><code>schema</code></em> and
          <em class="replaceable"><code>document</code></em> are required. As with
          JSON_VALID_SCHEMA(), the schema must be a valid JSON object,
          and the document must be a valid JSON document. Provided that
          these conditions are met, the function returns a report, as a
          JSON document, on the outcome of the validation. If the JSON
          document is considered valid according to the JSON Schema, the
          function returns a JSON object with one property
          <code class="literal">valid</code> having the value "true". If the JSON
          document fails validation, the function returns a JSON object
          which includes the properties listed here:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <code class="literal">valid</code>: Always "false" for a failed
              schema validation
            </p></li><li class="listitem"><p>
              <code class="literal">reason</code>: A human-readable string
              containing the reason for the failure
            </p></li><li class="listitem"><p>
              <code class="literal">schema-location</code>: A JSON pointer URI
              fragment identifier indicating where in the JSON schema
              the validation failed (see Note following this list)
            </p></li><li class="listitem"><p>
              <code class="literal">document-location</code>: A JSON pointer URI
              fragment identifier indicating where in the JSON document
              the validation failed (see Note following this list)
            </p></li><li class="listitem"><p>
              <code class="literal">schema-failed-keyword</code>: A string
              containing the name of the keyword or property in the JSON
              schema that was violated
</p></li></ul>
</div>
<a class="indexterm" name="idm46444320485776"></a>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            JSON pointer URI fragment identifiers are defined in
            <a class="ulink" href="https://tools.ietf.org/html/rfc6901#page-5" target="_top">RFC
            6901 - JavaScript Object Notation (JSON) Pointer</a>.
            (These are <span class="emphasis"><em>not</em></span> the same as the JSON
            path notation used by
            <a class="link" href="functions.html#function_json-extract"><code class="literal">JSON_EXTRACT()</code></a> and other
            MySQL JSON functions.) In this notation,
            <code class="literal">#</code> represents the entire document, and
            <code class="literal">#/myprop</code> represents the portion of the
            document included in the top-level property named
            <code class="literal">myprop</code>. See the specification just cited
            and the examples shown later in this section for more
            information.
</p>
</div>
<p>
          In this example, we set a user variable
          <code class="literal">@schema</code> to the value of a a JSON schema for
          geographical coordinates, and another one
          <code class="literal">@document</code> to the value of a JSON document
          containing one such coordinate. We then verify that
          <code class="literal">@document</code> validates according to
          <code class="literal">@schema</code> by using them as the arguments to
          <code class="literal">JSON_SCHEMA_VALIDATION_REORT()</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @schema = '{</code></strong>
    '&gt;  <strong class="userinput"><code>"id": "http://json-schema.org/geo",</code></strong>
    '&gt; <strong class="userinput"><code>"$schema": "http://json-schema.org/draft-04/schema#",</code></strong>
    '&gt; <strong class="userinput"><code>"description": "A geographical coordinate",</code></strong>
    '&gt; <strong class="userinput"><code>"type": "object",</code></strong>
    '&gt; <strong class="userinput"><code>"properties": {</code></strong>
    '&gt;   <strong class="userinput"><code>"latitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -90,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 90</code></strong>
    '&gt;   <strong class="userinput"><code>},</code></strong>
    '&gt;   <strong class="userinput"><code>"longitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -180,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 180</code></strong>
    '&gt;   <strong class="userinput"><code>}</code></strong>
    '&gt; <strong class="userinput"><code>},</code></strong>
    '&gt; <strong class="userinput"><code>"required": ["latitude", "longitude"]</code></strong>
    '&gt;<strong class="userinput"><code>}';</code></strong>
Query OK, 0 rows affected (0.01 sec)

mysql&gt; <strong class="userinput"><code>SET @document = '{</code></strong>
    '&gt; <strong class="userinput"><code>"latitude": 63.444697,</code></strong>
    '&gt; <strong class="userinput"><code>"longitude": 10.445118</code></strong>
    '&gt;<strong class="userinput"><code>}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_SCHEMA_VALIDATION_REPORT(@schema, @document);</code></strong>
+---------------------------------------------------+
| JSON_SCHEMA_VALIDATION_REPORT(@schema, @document) |
+---------------------------------------------------+
| {"valid": true}                                   |
+---------------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          Now we set <code class="literal">@document</code> such that it specifies
          an illegal value for one of its properties, like this:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @document = '{</code></strong>
    '&gt; <strong class="userinput"><code>"latitude": 63.444697,</code></strong>
    '&gt; <strong class="userinput"><code>"longitude": 310.445118</code></strong>
    '&gt; <strong class="userinput"><code>}';</code></strong>
</pre><p>
          Validation of <code class="literal">@document</code> now fails when
          tested with
          <code class="literal">JSON_SCHEMA_VALIDATION_REPORT()</code>. The output
          from the function call contains detailed information about the
          failure (with the function wrapped by
          <a class="link" href="functions.html#function_json-pretty"><code class="literal">JSON_PRETTY()</code></a> to provide better
          formatting), as shown here:
        </p><pre class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document))\G</code></strong>
*************************** 1. row ***************************
JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document)): {
  "valid": false,
  "reason": "The JSON document location '#/longitude' failed requirement 'maximum' at JSON Schema location '#/properties/longitude'",
  "schema-location": "#/properties/longitude",
  "document-location": "#/longitude",
  "schema-failed-keyword": "maximum"
}
1 row in set (0.00 sec)
</pre><p>
          Since <code class="literal">@schema</code> contains the
          <code class="literal">required</code> attribute, we can set
          <code class="literal">@document</code> to a value that is otherwise
          valid but does not contain the required properties, then test
          it against <code class="literal">@schema</code>. The output of
          <code class="literal">JSON_SCHEMA_VALIDATION_REPORT()</code> shows that
          validation fails due to lack of a required element, like this:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @document = '{}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document))\G</code></strong>
*************************** 1. row ***************************
JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document)): {
  "valid": false,
  "reason": "The JSON document location '#' failed requirement 'required' at JSON Schema location '#'",
  "schema-location": "#",
  "document-location": "#",
  "schema-failed-keyword": "required"
}
1 row in set (0.00 sec)
</pre><p>
          If we now set the value of <code class="literal">@schema</code> to the
          same JSON schema but without the <code class="literal">required</code>
          attribute, <code class="literal">@document</code> validates because it
          is a valid JSON object, even though it contains no properties,
          as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @schema = '{</code></strong>
    '&gt; <strong class="userinput"><code>"id": "http://json-schema.org/geo",</code></strong>
    '&gt; <strong class="userinput"><code>"$schema": "http://json-schema.org/draft-04/schema#",</code></strong>
    '&gt; <strong class="userinput"><code>"description": "A geographical coordinate",</code></strong>
    '&gt; <strong class="userinput"><code>"type": "object",</code></strong>
    '&gt; <strong class="userinput"><code>"properties": {</code></strong>
    '&gt;   <strong class="userinput"><code>"latitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -90,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 90</code></strong>
    '&gt;   <strong class="userinput"><code>},</code></strong>
    '&gt;   <strong class="userinput"><code>"longitude": {</code></strong>
    '&gt;     <strong class="userinput"><code>"type": "number",</code></strong>
    '&gt;     <strong class="userinput"><code>"minimum": -180,</code></strong>
    '&gt;     <strong class="userinput"><code>"maximum": 180</code></strong>
    '&gt;   <strong class="userinput"><code>}</code></strong>
    '&gt; <strong class="userinput"><code>}</code></strong>
    '&gt;<strong class="userinput"><code>}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_SCHEMA_VALIDATION_REPORT(@schema, @document);</code></strong>
+---------------------------------------------------+
| JSON_SCHEMA_VALIDATION_REPORT(@schema, @document) |
+---------------------------------------------------+
| {"valid": true}                                   |
+---------------------------------------------------+
1 row in set (0.00 sec)
</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="json-utility-functions"></a>12.17.8 JSON Utility Functions</h3>

</div>

</div>

</div>
<p>
      This section documents utility functions that act on JSON values,
      or strings that can be parsed as JSON values.
      <a class="link" href="functions.html#function_json-pretty"><code class="literal">JSON_PRETTY()</code></a> prints out a JSON
      value in a format that is easy to read.
      <a class="link" href="functions.html#function_json-storage-size"><code class="literal">JSON_STORAGE_SIZE()</code></a> and
      <a class="link" href="functions.html#function_json-storage-free"><code class="literal">JSON_STORAGE_FREE()</code></a> show,
      respectively, the amount of storage space used by a given JSON
      value and the amount of space remaining in a
      <code class="literal">JSON</code> column following a partial update.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_json-pretty"></a><p>
          <a class="indexterm" name="idm46444320409456"></a>

          <a class="link" href="functions.html#function_json-pretty"><code class="literal">JSON_PRETTY(<em class="replaceable"><code>json_val</code></em>)</code></a>
        </p><p>
          Provides pretty-printing of JSON values similar to that
          implemented in PHP and by other languages and database
          systems. The value supplied must be a JSON value or a valid
          string representation of a JSON value. Extraneous whitespaces
          and newlines present in this value have no effect on the
          output. For a <code class="literal">NULL</code> value, the function
          returns <code class="literal">NULL</code>. If the value is not a JSON
          document, or if it cannot be parsed as one, the function fails
          with an error.
        </p><p>
          Formatting of the output from this function adheres to the
          following rules:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Each array element or object member appears on a separate
              line, indented by one additional level as compared to its
              parent.
            </p></li><li class="listitem"><p>
              Each level of indentation adds two leading spaces.
            </p></li><li class="listitem"><p>
              A comma separating individual array elements or object
              members is printed before the newline that separates the
              two elements or members.
            </p></li><li class="listitem"><p>
              The key and the value of an object member are separated by
              a colon followed by a space ('<code class="literal">: </code>').
            </p></li><li class="listitem"><p>
              An empty object or array is printed on a single line. No
              space is printed between the opening and closing brace.
            </p></li><li class="listitem"><p>
              Special characters in string scalars and key names are
              escaped employing the same rules used by the
              <a class="link" href="functions.html#function_json-quote"><code class="literal">JSON_QUOTE()</code></a> function.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_PRETTY('123'); # scalar</code></strong>
+--------------------+
| JSON_PRETTY('123') |
+--------------------+
| 123                |
+--------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_PRETTY("[1,3,5]"); # array</code></strong>
+------------------------+
| JSON_PRETTY("[1,3,5]") |
+------------------------+
| [
  1,
  3,
  5
]      |
+------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_PRETTY('{"a":"10","b":"15","x":"25"}'); # object</code></strong>
+---------------------------------------------+
| JSON_PRETTY('{"a":"10","b":"15","x":"25"}') |
+---------------------------------------------+
| {
  "a": "10",
  "b": "15",
  "x": "25"
}   |
+---------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT JSON_PRETTY('["a",1,{"key1":</code></strong>
    '&gt;    <strong class="userinput"><code>"value1"},"5",     "77" ,</code></strong>
    '&gt;       <strong class="userinput"><code>{"key2":["value3","valueX",</code></strong>
    '&gt; <strong class="userinput"><code>"valueY"]},"j", "2"   ]')\G  # nested arrays and objects</code></strong>
*************************** 1. row ***************************
JSON_PRETTY('["a",1,{"key1":
             "value1"},"5",     "77" ,
                {"key2":["value3","valuex",
          "valuey"]},"j", "2"   ]'): [
  "a",
  1,
  {
    "key1": "value1"
  },
  "5",
  "77",
  {
    "key2": [
      "value3",
      "valuex",
      "valuey"
    ]
  },
  "j",
  "2"
]
</pre></li><li class="listitem"><a name="function_json-storage-free"></a><p>
          <a class="indexterm" name="idm46444320383728"></a>

          <a class="link" href="functions.html#function_json-storage-free"><code class="literal">JSON_STORAGE_FREE(<em class="replaceable"><code>json_val</code></em>)</code></a>
        </p><p>
          For a <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> column value, this
          function shows how much storage space was freed in its binary
          representation after it was updated in place using
          <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a>,
          <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a>, or
          <a class="link" href="functions.html#function_json-remove"><code class="literal">JSON_REMOVE()</code></a>. The argument can
          also be a valid JSON document or a string which can be parsed
          as one—either as a literal value or as the value of a
          user variable—in which case the function returns 0. It
          returns a positive, nonzero value if the argument is a
          <code class="literal">JSON</code> column value which has been updated as
          described previously, such that its binary representation
          takes up less space than it did prior to the update. For a
          <code class="literal">JSON</code> column which has been updated such
          that its binary representation is the same as or larger than
          before, or if the update was not able to take advantage of a
          partial update, it returns 0; it returns
          <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>.
        </p><p>
          If <em class="replaceable"><code>json_val</code></em> is not
          <code class="literal">NULL</code>, and neither is a valid JSON document
          nor can be successfully parsed as one, an error results.
        </p><p>
          In this example, we create a table containing a
          <code class="literal">JSON</code> column, then insert a row containing a
          JSON object:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE jtable (jcol JSON);</code></strong>
Query OK, 0 rows affected (0.38 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO jtable VALUES</code></strong>
    -&gt;     <strong class="userinput"><code>('{"a": 10, "b": "wxyz", "c": "[true, false]"}');</code></strong>
Query OK, 1 row affected (0.04 sec)

mysql&gt; <strong class="userinput"><code>SELECT * FROM jtable;</code></strong>
+----------------------------------------------+
| jcol                                         |
+----------------------------------------------+
| {"a": 10, "b": "wxyz", "c": "[true, false]"} |
+----------------------------------------------+
1 row in set (0.00 sec)
</pre><p>
          Now we update the column value using
          <code class="literal">JSON_SET()</code> such that a partial update can
          be performed; in this case, we replace the value pointed to by
          the <code class="literal">c</code> key (the array <code class="literal">[true,
          false]</code>) with one that takes up less space (the
          integer <code class="literal">1</code>):
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE jtable</code></strong>
    -&gt;     <strong class="userinput"><code>SET jcol = JSON_SET(jcol, "$.a", 10, "$.b", "wxyz", "$.c", 1);</code></strong>
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT * FROM jtable;</code></strong>
+--------------------------------+
| jcol                           |
+--------------------------------+
| {"a": 10, "b": "wxyz", "c": 1} |
+--------------------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_STORAGE_FREE(jcol) FROM jtable;</code></strong>
+-------------------------+
| JSON_STORAGE_FREE(jcol) |
+-------------------------+
|                      14 |
+-------------------------+
1 row in set (0.00 sec)
</pre><p>
          The effects of successive partial updates on this free space
          are cumulative, as shown in this example using
          <code class="literal">JSON_SET()</code> to reduce the space taken up by
          the value having key <code class="literal">b</code> (and making no other
          changes):
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE jtable</code></strong>
    -&gt;     <strong class="userinput"><code>SET jcol = JSON_SET(jcol, "$.a", 10, "$.b", "wx", "$.c", 1);</code></strong>
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT JSON_STORAGE_FREE(jcol) FROM jtable;</code></strong>
+-------------------------+
| JSON_STORAGE_FREE(jcol) |
+-------------------------+
|                      16 |
+-------------------------+
1 row in set (0.00 sec)
</pre><p>
          Updating the column without using
          <code class="literal">JSON_SET()</code>,
          <code class="literal">JSON_REPLACE()</code>, or
          <code class="literal">JSON_REMOVE()</code> means that the optimizer
          cannot perform the update in place; in this case,
          <code class="literal">JSON_STORAGE_FREE()</code> returns 0, as shown
          here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE jtable SET jcol = '{"a": 10, "b": 1}';</code></strong>
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT JSON_STORAGE_FREE(jcol) FROM jtable;</code></strong>
+-------------------------+
| JSON_STORAGE_FREE(jcol) |
+-------------------------+
|                       0 |
+-------------------------+
1 row in set (0.00 sec)
</pre><p>
          Partial updates of JSON documents can be performed only on
          column values. For a user variable that stores a JSON value,
          the value is always completely replaced, even when the update
          is performed using <code class="literal">JSON_SET()</code>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '{"a": 10, "b": "wxyz", "c": "[true, false]"}';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @j = JSON_SET(@j, '$.a', 10, '$.b', 'wxyz', '$.c', '1');</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @j, JSON_STORAGE_FREE(@j) AS Free;</code></strong>
+----------------------------------+------+
| @j                               | Free |
+----------------------------------+------+
| {"a": 10, "b": "wxyz", "c": "1"} |    0 |
+----------------------------------+------+
1 row in set (0.00 sec)
</pre><p>
          For a JSON literal, this function always returns 0:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_STORAGE_FREE('{"a": 10, "b": "wxyz", "c": "1"}') AS Free;</code></strong>
+------+
| Free |
+------+
|    0 |
+------+
1 row in set (0.00 sec)
</pre></li><li class="listitem"><a name="function_json-storage-size"></a><p>
          <a class="indexterm" name="idm46444320332736"></a>

          <a class="link" href="functions.html#function_json-storage-size"><code class="literal">JSON_STORAGE_SIZE(<em class="replaceable"><code>json_val</code></em>)</code></a>
        </p><p>
          This function returns the number of bytes used to store the
          binary representation of a JSON document. When the argument is
          a <code class="literal">JSON</code> column, this is the space used to
          store the JSON document as it was inserted into the column,
          prior to any partial updates that may have been performed on
          it afterwards. <em class="replaceable"><code>json_val</code></em> must be a
          valid JSON document or a string which can be parsed as one. In
          the case where it is string, the function returns the amount
          of storage space in the JSON binary representation that is
          created by parsing the string as JSON and converting it to
          binary. It returns <code class="literal">NULL</code> if the argument is
          <code class="literal">NULL</code>.
        </p><p>
          An error results when <em class="replaceable"><code>json_val</code></em> is
          not <code class="literal">NULL</code>, and is not—or cannot be
          successfully parsed as—a JSON document.
        </p><p>
          To illustrate this function's behavior when used with a
          <code class="literal">JSON</code> column as its argument, we create a
          table named <code class="literal">jtable</code> containing a
          <code class="literal">JSON</code> column <code class="literal">jcol</code>, insert
          a JSON value into the table, then obtain the storage space
          used by this column with
          <code class="literal">JSON_STORAGE_SIZE()</code>, as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE jtable (jcol JSON);</code></strong>
Query OK, 0 rows affected (0.42 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO jtable VALUES</code></strong>
    -&gt;     <strong class="userinput"><code>('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}');</code></strong>
Query OK, 1 row affected (0.04 sec)

mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt;     <strong class="userinput"><code>jcol,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_SIZE(jcol) AS Size,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_FREE(jcol) AS Free</code></strong>
    -&gt; <strong class="userinput"><code>FROM jtable;</code></strong>
+-----------------------------------------------+------+------+
| jcol                                          | Size | Free |
+-----------------------------------------------+------+------+
| {"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"} |   47 |    0 |
+-----------------------------------------------+------+------+
1 row in set (0.00 sec)
</pre><p>
          According to the output of
          <code class="literal">JSON_STORAGE_SIZE()</code>, the JSON document
          inserted into the column takes up 47 bytes. We also checked
          the amount of space freed by any previous partial updates of
          the column using
          <a class="link" href="functions.html#function_json-storage-free"><code class="literal">JSON_STORAGE_FREE()</code></a>; since no
          updates have yet been performed, this is 0, as expected.
        </p><p>
          Next we perform an <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> on
          the table that should result in a partial update of the
          document stored in <code class="literal">jcol</code>, and then test the
          result as shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE jtable SET jcol = </code></strong>
    -&gt;     <strong class="userinput"><code>JSON_SET(jcol, "$.b", "a");</code></strong>
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt;     <strong class="userinput"><code>jcol,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_SIZE(jcol) AS Size,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_FREE(jcol) AS Free</code></strong>
    -&gt; <strong class="userinput"><code>FROM jtable;</code></strong>
+--------------------------------------------+------+------+
| jcol                                       | Size | Free |
+--------------------------------------------+------+------+
| {"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"} |   47 |    3 |
+--------------------------------------------+------+------+
1 row in set (0.00 sec)
</pre><p>
          The value returned by <code class="literal">JSON_STORAGE_FREE()</code>
          in the previous query indicates that a partial update of the
          JSON document was performed, and that this freed 3 bytes of
          space used to store it. The result returned by
          <code class="literal">JSON_STORAGE_SIZE()</code> is unchanged by the
          partial update.
        </p><p>
          Partial updates are supported for updates using
          <a class="link" href="functions.html#function_json-set"><code class="literal">JSON_SET()</code></a>,
          <a class="link" href="functions.html#function_json-replace"><code class="literal">JSON_REPLACE()</code></a>, or
          <a class="link" href="functions.html#function_json-remove"><code class="literal">JSON_REMOVE()</code></a>. The direct
          assignment of a value to a <code class="literal">JSON</code> column
          cannot be partially updated; following such an update,
          <code class="literal">JSON_STORAGE_SIZE()</code> always shows the
          storage used for the newly-set value:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE jtable</code></strong>
mysql&gt;     <strong class="userinput"><code>SET jcol = '{"a": 4.55, "b": "wxyz", "c": "[true, false]"}';</code></strong>
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt;     <strong class="userinput"><code>jcol,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_SIZE(jcol) AS Size,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_FREE(jcol) AS Free</code></strong>
    -&gt; <strong class="userinput"><code>FROM jtable;</code></strong>
+------------------------------------------------+------+------+
| jcol                                           | Size | Free |
+------------------------------------------------+------+------+
| {"a": 4.55, "b": "wxyz", "c": "[true, false]"} |   56 |    0 |
+------------------------------------------------+------+------+
1 row in set (0.00 sec)
</pre><p>
          A JSON user variable cannot be partially updated. This means
          that this function always shows the space currently used to
          store a JSON document in a user variable:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @j = '[100, "sakila", [1, 3, 5], 425.05]';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;</code></strong>
+------------------------------------+------+
| @j                                 | Size |
+------------------------------------+------+
| [100, "sakila", [1, 3, 5], 425.05] |   45 |
+------------------------------------+------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @j = JSON_SET(@j, '$[1]', "json");</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;</code></strong>
+----------------------------------+------+
| @j                               | Size |
+----------------------------------+------+
| [100, "json", [1, 3, 5], 425.05] |   43 |
+----------------------------------+------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SET @j = JSON_SET(@j, '$[2][0]', JSON_ARRAY(10, 20, 30));</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;</code></strong>
+---------------------------------------------+------+
| @j                                          | Size |
+---------------------------------------------+------+
| [100, "json", [[10, 20, 30], 3, 5], 425.05] |   56 |
+---------------------------------------------+------+
1 row in set (0.00 sec)
</pre><p>
          For a JSON literal, this function always returns the current
          storage space used:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,</code></strong>
    -&gt;     <strong class="userinput"><code>JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D;</code></strong>
+----+----+----+----+
| A  | B  | C  | D  |
+----+----+----+----+
| 45 | 44 | 47 | 56 |
+----+----+----+----+
1 row in set (0.00 sec)
</pre></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="gtid-functions"></a>12.18 Functions Used with Global Transaction Identifiers (GTIDs)</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444320270208"></a><a class="indexterm" name="idm46444320269168"></a><p>
      The functions described in this section are used with GTID-based
      replication. It is important to keep in mind that all of these
      functions take string representations of GTID sets as arguments.
      As such, the GTID sets must always be quoted when used with them.
      See <a class="xref" href="replication.html#replication-gtids-concepts-gtid-sets" title="GTID Sets">GTID Sets</a> for
      more information.
    </p><p>
      The union of two GTID sets is simply their representations as
      strings, joined together with an interposed comma. In other words,
      you can define a very simple function for obtaining the union of
      two GTID sets, similar to that created here:
    </p><pre data-lang="sql" class="programlisting">CREATE FUNCTION GTID_UNION(g1 TEXT, g2 TEXT)
    RETURNS TEXT DETERMINISTIC
    RETURN CONCAT(g1,',',g2);</pre><p>
      For more information about GTIDs and how these GTID functions are
      used in practice, see <a class="xref" href="replication.html#replication-gtids" title="17.1.3 Replication with Global Transaction Identifiers">Section 17.1.3, “Replication with Global Transaction Identifiers”</a>.
</p>
<div class="table">
<a name="idm46444320263232"></a><p class="title"><b>Table 12.23 GTID Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists functions used with global transaction identifiers (GTIDs)."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_gtid-subset"><code class="literal">GTID_SUBSET()</code></a></td>
<td>
      Return true if all GTIDs in subset are also in set; otherwise
      false.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_gtid-subtract"><code class="literal">GTID_SUBTRACT()</code></a></td>
<td>
      Return all GTIDs in set that are not in subset.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_wait-for-executed-gtid-set"><code class="literal">WAIT_FOR_EXECUTED_GTID_SET()</code></a></td>
<td>
      Wait until the given GTIDs have executed on the slave.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_wait-until-sql-thread-after-gtids"><code class="literal">WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()</code></a> (deprecated 8.0.18)</td>
<td>
      Use <code class="literal">WAIT_FOR_EXECUTED_GTID_SET()</code>.
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_gtid-subset"></a><p>
          <a class="indexterm" name="idm46444320240336"></a>

          <a class="link" href="functions.html#function_gtid-subset"><code class="literal">GTID_SUBSET(<em class="replaceable"><code>set1</code></em>,<em class="replaceable"><code>set2</code></em>)</code></a>
        </p><p>
          Given two sets of global transaction identifiers
          <em class="replaceable"><code>set1</code></em> and
          <em class="replaceable"><code>set2</code></em>, returns true if all GTIDs in
          <em class="replaceable"><code>set1</code></em> are also in
          <em class="replaceable"><code>set2</code></em>. Returns false otherwise.
        </p><p>
          The GTID sets used with this function are represented as
          strings, as shown in the following examples:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23',</code></strong>
    -&gt;     <strong class="userinput"><code>'3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G</code></strong>
*************************** 1. row ***************************
GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 1
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23-25',</code></strong>
    -&gt;     <strong class="userinput"><code>'3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G</code></strong>
*************************** 1. row ***************************
GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23-25',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 1
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25',</code></strong>
    -&gt;     <strong class="userinput"><code>'3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G</code></strong>
*************************** 1. row ***************************
GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 0
1 row in set (0.00 sec)
</pre></li><li class="listitem"><a name="function_gtid-subtract"></a><p>
          <a class="indexterm" name="idm46444320223312"></a>

          <a class="link" href="functions.html#function_gtid-subtract"><code class="literal">GTID_SUBTRACT(<em class="replaceable"><code>set1</code></em>,<em class="replaceable"><code>set2</code></em>)</code></a>
        </p><p>
          Given two sets of global transaction identifiers
          <em class="replaceable"><code>set1</code></em> and
          <em class="replaceable"><code>set2</code></em>, returns only those GTIDs from
          <em class="replaceable"><code>set1</code></em> that are not in
          <em class="replaceable"><code>set2</code></em>.
        </p><p>
          All GTID sets used with this function are represented as
          strings and must be quoted, as shown in these examples:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',</code></strong>
    -&gt;     <strong class="userinput"><code>'3E11FA47-71CA-11E1-9E33-C80AA9429562:21')\G</code></strong>
*************************** 1. row ***************************
GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:22-57
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',</code></strong>
    -&gt;     <strong class="userinput"><code>'3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25')\G</code></strong>
*************************** 1. row ***************************
GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:26-57
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',</code></strong>
    -&gt;     <strong class="userinput"><code>'3E11FA47-71CA-11E1-9E33-C80AA9429562:23-24')\G</code></strong>
*************************** 1. row ***************************
GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:23-24'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:21-22:25-57
1 row in set (0.01 sec)
</pre></li><li class="listitem"><a name="function_wait-for-executed-gtid-set"></a><p>
          <a class="indexterm" name="idm46444320205984"></a>

          <a class="link" href="functions.html#function_wait-for-executed-gtid-set"><code class="literal">WAIT_FOR_EXECUTED_GTID_SET(<em class="replaceable"><code>gtid_set</code></em>[,
          <em class="replaceable"><code>timeout</code></em>])</code></a>
        </p><p>
          Wait until the server has applied all of the transactions
          whose global transaction identifiers are contained in
          <em class="replaceable"><code>gtid_set</code></em>; that is, until the
          condition GTID_SUBSET(<em class="replaceable"><code>gtid_subset</code></em>,
          <code class="literal">@@GLOBAL.gtid_executed</code>) holds. See
          <a class="xref" href="replication.html#replication-gtids-concepts" title="17.1.3.1 GTID Format and Storage">Section 17.1.3.1, “GTID Format and Storage”</a> for a definition
          of GTID sets.
        </p><p>
          If a timeout is specified, and
          <em class="replaceable"><code>timeout</code></em> seconds elapse before all
          of the transactions in the GTID set have been applied, the
          function stops waiting. <em class="replaceable"><code>timeout</code></em> is
          optional, and the default timeout is 0 seconds, in which case
          the function always waits until all of the transactions in the
          GTID set have been applied.
        </p><p>
          <code class="literal">WAIT_FOR_EXECUTED_GTID_SET()</code> monitors all
          the GTIDs that are applied on the server, including
          transactions that arrive from all replication channels and
          user clients. It does not take into account whether
          replication channels have been started or stopped.
        </p><p>
          For more information, see <a class="xref" href="replication.html#replication-gtids" title="17.1.3 Replication with Global Transaction Identifiers">Section 17.1.3, “Replication with Global Transaction Identifiers”</a>.
        </p><p>
          GTID sets used with this function are represented as strings
          and so must be quoted as shown in the following example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT WAIT_FOR_EXECUTED_GTID_SET('3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5');</code></strong>
        -&gt; 0
</pre><p>
          For a syntax description for GTID sets, see
          <a class="xref" href="replication.html#replication-gtids-concepts" title="17.1.3.1 GTID Format and Storage">Section 17.1.3.1, “GTID Format and Storage”</a>.
        </p><p>
          For <code class="literal">WAIT_FOR_EXECUTED_GTID_SET()</code>, the
          return value is the state of the query, where 0 represents
          success, and 1 represents timeout. Any other failures generate
          an error.
        </p><p>
          <a class="link" href="replication.html#sysvar_gtid_mode"><code class="literal">gtid_mode</code></a> cannot be changed
          to OFF while any client is using this function to wait for
          GTIDs to be applied.
        </p></li><li class="listitem"><a name="function_wait-until-sql-thread-after-gtids"></a><p>
          <a class="indexterm" name="idm46444320184384"></a>

          <a class="link" href="functions.html#function_wait-until-sql-thread-after-gtids"><code class="literal">WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(<em class="replaceable"><code>gtid_set</code></em>[,
          <em class="replaceable"><code>timeout</code></em>][,<em class="replaceable"><code>channel</code></em>])</code></a>
        </p><p>
          <code class="literal">WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()</code> is
          deprecated. Use
          <code class="literal">WAIT_FOR_EXECUTED_GTID_SET()</code> instead, which
          works regardless of the replication channel or user client
          through which the specified transactions arrive on the server.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="enterprise-encryption"></a>12.19 MySQL Enterprise Encryption Functions</h2>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#enterprise-encryption-installation">12.19.1 MySQL Enterprise Encryption Installation</a></span></dt><dt><span class="section"><a href="functions.html#enterprise-encryption-usage">12.19.2 MySQL Enterprise Encryption Usage and Examples</a></span></dt><dt><span class="section"><a href="functions.html#enterprise-encryption-function-reference">12.19.3 MySQL Enterprise Encryption Function Reference</a></span></dt><dt><span class="section"><a href="functions.html#enterprise-encryption-functions">12.19.4 MySQL Enterprise Encryption Function Descriptions</a></span></dt></dl>
</div>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<div class="admon-title">
Note
</div>
<p>
        MySQL Enterprise Encryption is an extension included in MySQL Enterprise Edition, a commercial
        product. To learn more about commercial products,
        <a class="ulink" href="https://www.mysql.com/products/" target="_top">https://www.mysql.com/products/</a>.
</p>
</div>
<p>
      MySQL Enterprise Edition includes a set of encryption functions based on the OpenSSL
      library that expose OpenSSL capabilities at the SQL level. These
      functions enable Enterprise applications to perform the following
      operations:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Implement added data protection using public-key asymmetric
          cryptography
        </p></li><li class="listitem"><p>
          Create public and private keys and digital signatures
        </p></li><li class="listitem"><p>
          Perform asymmetric encryption and decryption
        </p></li><li class="listitem"><p>
          Use cryptographic hashing for digital signing and data
          verification and validation
</p></li></ul>
</div>
<p>
      MySQL Enterprise Encryption supports the RSA, DSA, and DH cryptographic
      algorithms.
    </p><p>
      MySQL Enterprise Encryption is supplied as a user-defined function (UDF) library,
      from which individual functions can be installed individually.
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="enterprise-encryption-installation"></a>12.19.1 MySQL Enterprise Encryption Installation</h3>
</div>
</div>
</div>
<p>
        MySQL Enterprise Encryption functions are located in a user-defined function
        (UDF) library file installed in the plugin directory (the
        directory named by the
        <a class="link" href="server-administration.html#sysvar_plugin_dir"><code class="literal">plugin_dir</code></a> system variable).
        The UDF library base name is <code class="filename">openssl_udf</code>
        and the suffix is platform dependent. For example, the file name
        on Linux or Windows is <code class="filename">openssl_udf.so</code> or
        <code class="filename">openssl_udf.dll</code>, respectively.
      </p><p>
        To install functions from the library file, use the
        <a class="link" href="sql-statements.html#create-function-udf" title="13.7.4.1 CREATE FUNCTION Syntax for User-Defined Functions"><code class="literal">CREATE
        FUNCTION</code></a> statement. To load all functions from the
        library, use this set of statements (adjust the file name suffix
        as necessary):
      </p><pre data-lang="sql" class="programlisting">CREATE FUNCTION asymmetric_decrypt RETURNS STRING
  SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_derive RETURNS STRING
  SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_encrypt RETURNS STRING
  SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_sign RETURNS STRING
  SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_verify RETURNS INTEGER
  SONAME 'openssl_udf.so';
CREATE FUNCTION create_asymmetric_priv_key RETURNS STRING
  SONAME 'openssl_udf.so';
CREATE FUNCTION create_asymmetric_pub_key RETURNS STRING
  SONAME 'openssl_udf.so';
CREATE FUNCTION create_dh_parameters RETURNS STRING
  SONAME 'openssl_udf.so';
CREATE FUNCTION create_digest RETURNS STRING
  SONAME 'openssl_udf.so';</pre><p>
        Once installed, UDFs remain installed across server restarts. To
        unload UDFs, use the
        <a class="link" href="sql-statements.html#drop-function-udf" title="13.7.4.2 DROP FUNCTION Statement"><code class="literal">DROP
        FUNCTION</code></a> statement. For example, to unload the
        key-generation functions, do this:
      </p><pre data-lang="sql" class="programlisting">DROP FUNCTION create_asymmetric_priv_key;
DROP FUNCTION create_asymmetric_pub_key;</pre><p>
        In the
        <a class="link" href="sql-statements.html#create-function-udf" title="13.7.4.1 CREATE FUNCTION Syntax for User-Defined Functions"><code class="literal">CREATE
        FUNCTION</code></a> and
        <a class="link" href="sql-statements.html#drop-function-udf" title="13.7.4.2 DROP FUNCTION Statement"><code class="literal">DROP
        FUNCTION</code></a> statements, the function names must be
        specified in lowercase. This differs from their use at function
        invocation time, for which you can use any lettercase.
      </p><p>
        The <a class="link" href="sql-statements.html#create-function-udf" title="13.7.4.1 CREATE FUNCTION Syntax for User-Defined Functions"><code class="literal">CREATE
        FUNCTION</code></a> and
        <a class="link" href="sql-statements.html#drop-function-udf" title="13.7.4.2 DROP FUNCTION Statement"><code class="literal">DROP
        FUNCTION</code></a> statements require the
        <a class="link" href="security.html#priv_insert"><code class="literal">INSERT</code></a> and
        <a class="link" href="security.html#priv_drop"><code class="literal">DROP</code></a> privilege, respectively, for
        the <code class="literal">mysql</code> database.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="enterprise-encryption-usage"></a>12.19.2 MySQL Enterprise Encryption Usage and Examples</h3>

</div>

</div>

</div>
<p>
        To use MySQL Enterprise Encryption in applications, invoke the functions that
        are appropriate for the operations you wish to perform. This
        section demonstrates how to carry out some representative tasks:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><a class="xref" href="functions.html#enterprise-encryption-usage-create-key-pair" title="Create a private/public key pair using RSA encryption">Create a private/public key pair using RSA encryption</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#enterprise-encryption-usage-encrypt-decrypt" title="Use the private key to encrypt data and the public key to decrypt it">Use the private key to encrypt data and the public key to decrypt it</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#enterprise-encryption-usage-create-digest" title="Generate a digest from a string">Generate a digest from a string</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#enterprise-encryption-usage-digital-signing" title="Use the digest with a key pair">Use the digest with a key pair</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#enterprise-encryption-usage-create-symmetic-key" title="Create a symmetric key">Create a symmetric key</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#enterprise-encryption-usage-limit-cpu" title="Limit CPU usage by key-generation operations">Limit CPU usage by key-generation operations</a></p></li></ul>
</div>

<div class="simplesect">

<div class="titlepage">
<div>

<div class="simple">
<h4 class="title"><a name="enterprise-encryption-usage-create-key-pair"></a>Create a private/public key pair using RSA encryption</h4>

</div>

</div>

</div>
<pre data-lang="sql" class="programlisting">-- Encryption algorithm; can be 'DSA' or 'DH' instead
SET @algo = 'RSA';
-- Key length in bits; make larger for stronger keys
SET @key_len = 1024;

-- Create private key
SET @priv = CREATE_ASYMMETRIC_PRIV_KEY(@algo, @key_len);
-- Derive corresponding public key from private key, using same algorithm
SET @pub = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv);</pre><p>
          Now you can use the key pair to encrypt and decrypt data, sign
          and verify data, or generate symmetric keys.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="enterprise-encryption-usage-encrypt-decrypt"></a>Use the private key to encrypt data and the public key to decrypt it</h4>

</div>

</div>

</div>
<p>
          This requires that the members of the key pair be RSA keys.
        </p><pre data-lang="sql" class="programlisting">SET @ciphertext = ASYMMETRIC_ENCRYPT(@algo, 'My secret text', @priv);
SET @plaintext = ASYMMETRIC_DECRYPT(@algo, @ciphertext, @pub);</pre><p>
          Conversely, you can encrypt using the public key and decrypt
          using the private key.
        </p><pre data-lang="sql" class="programlisting">SET @ciphertext = ASYMMETRIC_ENCRYPT(@algo, 'My secret text', @pub);
SET @plaintext = ASYMMETRIC_DECRYPT(@algo, @ciphertext, @priv);</pre><p>
          In either case, the algorithm specified for the encryption and
          decryption functions must match that used to generate the
          keys.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="enterprise-encryption-usage-create-digest"></a>Generate a digest from a string</h4>

</div>

</div>

</div>
<pre data-lang="sql" class="programlisting">-- Digest type; can be 'SHA256', 'SHA384', or 'SHA512' instead
SET @dig_type = 'SHA224';

-- Generate digest string
SET @dig = CREATE_DIGEST(@dig_type, 'My text to digest');</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="enterprise-encryption-usage-digital-signing"></a>Use the digest with a key pair</h4>

</div>

</div>

</div>
<p>
          The key pair can be used to sign data, then verify that the
          signature matches the digest.
        </p><pre data-lang="sql" class="programlisting">-- Encryption algorithm; could be 'DSA' instead; keys must
-- have been created using same algorithm
SET @algo = 'RSA';

-- Generate signature for digest and verify signature against digest
SET @sig = ASYMMETRIC_SIGN(@algo, @dig, @priv, @dig_type);
-- Verify signature against digest
SET @verf = ASYMMETRIC_VERIFY(@algo, @dig, @sig, @pub, @dig_type);</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="enterprise-encryption-usage-create-symmetic-key"></a>Create a symmetric key</h4>

</div>

</div>

</div>
<p>
          This requires DH private/public keys as inputs, created using
          a shared symmetric secret. Create the secret by passing the
          key length to
          <a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a>, then
          pass the secret as the <span class="quote">“<span class="quote">key length</span>”</span> to
          <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>.
        </p><pre data-lang="sql" class="programlisting">-- Generate DH shared symmetric secret
SET @dhp = CREATE_DH_PARAMETERS(1024);
-- Generate DH key pairs
SET @algo = 'DH';
SET @priv1 = CREATE_ASYMMETRIC_PRIV_KEY(@algo, @dhp);
SET @pub1 = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv1);
SET @priv2 = CREATE_ASYMMETRIC_PRIV_KEY(@algo, @dhp);
SET @pub2 = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv2);

-- Generate symmetric key using public key of first party,
-- private key of second party
SET @sym1 = ASYMMETRIC_DERIVE(@pub1, @priv2);

-- Or use public key of second party, private key of first party
SET @sym2 = ASYMMETRIC_DERIVE(@pub2, @priv1);</pre><p>
          Key string values can be created at runtime and stored into a
          variable or table using
          <a class="link" href="sql-statements.html#set-variable" title="13.7.6.1 SET Syntax for Variable Assignment"><code class="literal">SET</code></a>,
          <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>, or
          <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a>:
        </p><pre data-lang="sql" class="programlisting">SET @priv1 = CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024);
SELECT CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024) INTO @priv2;
INSERT INTO t (key_col) VALUES(CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024));</pre><p>
          Key string values stored in files can be read using the
          <a class="link" href="functions.html#function_load-file"><code class="literal">LOAD_FILE()</code></a> function by users
          who have the <a class="link" href="security.html#priv_file"><code class="literal">FILE</code></a> privilege.
        </p><p>
          Digest and signature strings can be handled similarly.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="enterprise-encryption-usage-limit-cpu"></a>Limit CPU usage by key-generation operations</h4>

</div>

</div>

</div>
<p>
          The
          <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>
          and <a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a>
          encryption functions take a key-length parameter, and the
          amount of CPU resources required by these functions increases
          as the key length increases. For some installations, this
          might result in unacceptable CPU usage if applications
          frequently generate excessively long keys.
        </p><p>
          OpenSSL imposes a minimum key length of 1,024 bits for all
          keys. OpenSSL also imposes a maximum key length of 10,000 bits
          and 16,384 bits for DSA and RSA keys, respectively, for
          <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>,
          and a maximum key length of 10,000 bits for
          <a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a>. If
          those maximum values are too high, three environment variables
          are available to enable MySQL server administrators to set
          lower maximum lengths for key generation, and thereby to limit
          CPU usage:
</p><a class="indexterm" name="idm46444320102496"></a><a class="indexterm" name="idm46444320101376"></a><a class="indexterm" name="idm46444320099920"></a><a class="indexterm" name="idm46444320098800"></a><a class="indexterm" name="idm46444320097296"></a><a class="indexterm" name="idm46444320096176"></a>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
              <code class="literal">MYSQL_OPENSSL_UDF_DSA_BITS_THRESHOLD</code>:
              Maximum DSA key length in bits for
              <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>.
              The minimum and maximum values for this variable are 1,024
              and 10,000.
            </p></li><li class="listitem"><p>
              <code class="literal">MYSQL_OPENSSL_UDF_RSA_BITS_THRESHOLD</code>:
              Maximum RSA key length in bits for
              <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>.
              The minimum and maximum values for this variable are 1,024
              and 16,384.
            </p></li><li class="listitem"><p>
              <code class="literal">MYSQL_OPENSSL_UDF_DH_BITS_THRESHOLD</code>:
              Maximum key length in bits for
              <a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a>. The
              minimum and maximum values for this variable are 1,024 and
              10,000.
</p></li></ul>
</div>
<p>
          To use any of these environment variables, set them in the
          environment of the process that starts the server. If set,
          their values take precedence over the maximum key lengths
          imposed by OpenSSL. For example, to set a maximum key length
          of 4,096 bits for DSA and RSA keys for
          <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>,
          set these variables:
        </p><pre data-lang="terminal" class="programlisting">export MYSQL_OPENSSL_UDF_DSA_BITS_THRESHOLD=4096
export MYSQL_OPENSSL_UDF_RSA_BITS_THRESHOLD=4096</pre><p>
          The example uses Bourne shell syntax. The syntax for other
          shells may differ.
</p>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="enterprise-encryption-function-reference"></a>12.19.3 MySQL Enterprise Encryption Function Reference</h3>

</div>

</div>

</div>

<div class="table">
<a name="idm46444320080416"></a><p class="title"><b>Table 12.24 MySQL Enterprise Encryption Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists MySQL Enterprise Encryption functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-decrypt"><code class="literal">ASYMMETRIC_DECRYPT()</code></a></td>
<td>
      Decrypt ciphertext using private or public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-derive"><code class="literal">ASYMMETRIC_DERIVE()</code></a></td>
<td>
      Derive symmetric key from asymmetric keys
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a></td>
<td>
      Encrypt cleartext using private or public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-sign"><code class="literal">ASYMMETRIC_SIGN()</code></a></td>
<td>
      Generate signature from digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_asymmetric-verify"><code class="literal">ASYMMETRIC_VERIFY()</code></a></td>
<td>
      Verify that signature matches digest
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a></td>
<td>
      Create private key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-asymmetric-pub-key"><code class="literal">CREATE_ASYMMETRIC_PUB_KEY()</code></a></td>
<td>
      Create public key
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a></td>
<td>
      Generate shared DH secret
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_create-digest"><code class="literal">CREATE_DIGEST()</code></a></td>
<td>
      Generate digest from string
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="enterprise-encryption-functions"></a>12.19.4 MySQL Enterprise Encryption Function Descriptions</h3>

</div>

</div>

</div>
<p>
        MySQL Enterprise Encryption functions have these general characteristics:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            For arguments of the wrong type or an incorrect number of
            arguments, each function returns an error.
          </p></li><li class="listitem"><p>
            If the arguments are not suitable to permit a function to
            perform the requested operation, it returns
            <code class="literal">NULL</code> or 0 as appropriate. This occurs,
            for example, if a function does not support a specified
            algorithm, a key length is too short or long, or a string
            expected to be a key string in PEM format is not a valid
            key. (OpenSSL imposes its own key-length limits, and server
            administrators can impose additional limits on maximum key
            length by setting environment variables. See
            <a class="xref" href="functions.html#enterprise-encryption-usage" title="12.19.2 MySQL Enterprise Encryption Usage and Examples">Section 12.19.2, “MySQL Enterprise Encryption Usage and Examples”</a>.)
          </p></li><li class="listitem"><p>
            The underlying SSL library takes care of randomness
            initialization.
</p></li></ul>
</div>
<p>
        Several of the functions take an encryption algorithm argument.
        The following table summarizes the supported algorithms by
        function.
</p>
<div class="table">
<a name="idm46444320037264"></a><p class="title"><b>Table 12.25 Supported Algorithms by Function</b></p>
<div class="table-contents">
<table summary="Supported encryption algorithms by function."><col width="50%"><col width="50%"><thead><tr>
            <th scope="col">Function</th>
            <th scope="col">Supported Algorithms</th>
          </tr></thead><tbody><tr>
            <td scope="row"><a class="link" href="functions.html#function_asymmetric-decrypt"><code class="literal">ASYMMETRIC_DECRYPT()</code></a></td>
            <td>RSA</td>
          </tr><tr>
            <td scope="row"><a class="link" href="functions.html#function_asymmetric-derive"><code class="literal">ASYMMETRIC_DERIVE()</code></a></td>
            <td>DH</td>
          </tr><tr>
            <td scope="row"><a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a></td>
            <td>RSA</td>
          </tr><tr>
            <td scope="row"><a class="link" href="functions.html#function_asymmetric-sign"><code class="literal">ASYMMETRIC_SIGN()</code></a></td>
            <td>RSA, DSA</td>
          </tr><tr>
            <td scope="row"><a class="link" href="functions.html#function_asymmetric-verify"><code class="literal">ASYMMETRIC_VERIFY()</code></a></td>
            <td>RSA, DSA</td>
          </tr><tr>
            <td scope="row"><a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a></td>
            <td>RSA, DSA, DH</td>
          </tr><tr>
            <td scope="row"><a class="link" href="functions.html#function_create-asymmetric-pub-key"><code class="literal">CREATE_ASYMMETRIC_PUB_KEY()</code></a></td>
            <td>RSA, DSA, DH</td>
          </tr><tr>
            <td scope="row"><a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a></td>
            <td>DH</td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
          Although you can create keys using any of the RSA, DSA, or DH
          encryption algorithms, other functions that take key arguments
          might accept only certain types of keys. For example,
          <a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a> and
          <a class="link" href="functions.html#function_asymmetric-decrypt"><code class="literal">ASYMMETRIC_DECRYPT()</code></a> accept
          only RSA keys.
</p>
</div>
<p>
        The following descriptions describe the calling sequences for
        MySQL Enterprise Encryption functions. For additional examples and discussion,
        see <a class="xref" href="functions.html#enterprise-encryption-usage" title="12.19.2 MySQL Enterprise Encryption Usage and Examples">Section 12.19.2, “MySQL Enterprise Encryption Usage and Examples”</a>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_asymmetric-decrypt"></a><p>
            <a class="indexterm" name="idm46444319997008"></a>

            <a class="link" href="functions.html#function_asymmetric-decrypt"><code class="literal">ASYMMETRIC_DECRYPT(<em class="replaceable"><code>algorithm</code></em>,
            <em class="replaceable"><code>crypt_str</code></em>,
            <em class="replaceable"><code>key_str</code></em>)</code></a>
          </p><p>
            Decrypts an encrypted string using the given algorithm and
            key string, and returns the resulting plaintext as a binary
            string. If decryption fails, the result is
            <code class="literal">NULL</code>.
          </p><p>
            <em class="replaceable"><code>key_str</code></em> must be a valid key
            string in PEM format. For successful decryption, it must be
            the public or private key string corresponding to the
            private or public key string used with
            <a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a> to
            produce the encrypted string.
            <em class="replaceable"><code>algorithm</code></em> indicates the
            encryption algorithm used to create the key.
          </p><p>
            Supported <em class="replaceable"><code>algorithm</code></em> values:
            <code class="literal">'RSA'</code>
          </p><p>
            For a usage example, see the description of
            <a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a>.
          </p></li><li class="listitem"><a name="function_asymmetric-derive"></a><p>
            <a class="indexterm" name="idm46444319981776"></a>

            <a class="link" href="functions.html#function_asymmetric-derive"><code class="literal">ASYMMETRIC_DERIVE(<em class="replaceable"><code>pub_key_str</code></em>,
            <em class="replaceable"><code>priv_key_str</code></em>)</code></a>
          </p><p>
            Derives a symmetric key using the private key of one party
            and the public key of another, and returns the resulting key
            as a binary string. If key derivation fails, the result is
            <code class="literal">NULL</code>.
          </p><p>
            <em class="replaceable"><code>pub_key_str</code></em> and
            <em class="replaceable"><code>priv_key_str</code></em> must be valid key
            strings in PEM format. They must be created using the DH
            algorithm.
          </p><p>
            Suppose that you have two pairs of public and private keys:
          </p><pre data-lang="sql" class="programlisting">SET @dhp = CREATE_DH_PARAMETERS(1024);
SET @priv1 = CREATE_ASYMMETRIC_PRIV_KEY('DH', @dhp);
SET @pub1 = CREATE_ASYMMETRIC_PUB_KEY('DH', @priv1);
SET @priv2 = CREATE_ASYMMETRIC_PRIV_KEY('DH', @dhp);
SET @pub2 = CREATE_ASYMMETRIC_PUB_KEY('DH', @priv2);</pre><p>
            Suppose further that you use the private key from one pair
            and the public key from the other pair to create a symmetric
            key string. Then this symmetric key identity relationship
            holds:
          </p><pre data-lang="sql" class="programlisting">ASYMMETRIC_DERIVE(@pub1, @priv2) = ASYMMETRIC_DERIVE(@pub2, @priv1)</pre></li><li class="listitem"><a name="function_asymmetric-encrypt"></a><p>
            <a class="indexterm" name="idm46444319968464"></a>

            <a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT(<em class="replaceable"><code>algorithm</code></em>,
            <em class="replaceable"><code>str</code></em>,
            <em class="replaceable"><code>key_str</code></em>)</code></a>
          </p><p>
            Encrypts a string using the given algorithm and key string,
            and returns the resulting ciphertext as a binary string. If
            encryption fails, the result is <code class="literal">NULL</code>.
          </p><p>
            The <em class="replaceable"><code>str</code></em> length cannot be greater
            than the <em class="replaceable"><code>key_str</code></em> length −
            11, in bytes
          </p><p>
            <em class="replaceable"><code>key_str</code></em> must be a valid key
            string in PEM format. <em class="replaceable"><code>algorithm</code></em>
            indicates the encryption algorithm used to create the key.
          </p><p>
            Supported <em class="replaceable"><code>algorithm</code></em> values:
            <code class="literal">'RSA'</code>
          </p><p>
            To encrypt a string, pass a private or public key string to
            <a class="link" href="functions.html#function_asymmetric-encrypt"><code class="literal">ASYMMETRIC_ENCRYPT()</code></a>. To
            recover the original unencrypted string, pass the encrypted
            string to
            <a class="link" href="functions.html#function_asymmetric-decrypt"><code class="literal">ASYMMETRIC_DECRYPT()</code></a>, along
            with the public or private key string correponding to the
            private or public key string used for encryption.
          </p><pre data-lang="sql" class="programlisting">-- Generate private/public key pair
SET @priv = CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024);
SET @pub = CREATE_ASYMMETRIC_PUB_KEY('RSA', @priv);

-- Encrypt using private key, decrypt using public key
SET @ciphertext = ASYMMETRIC_ENCRYPT('RSA', 'The quick brown fox', @priv);
SET @plaintext = ASYMMETRIC_DECRYPT('RSA', @ciphertext, @pub);

-- Encrypt using public key, decrypt using private key
SET @ciphertext = ASYMMETRIC_ENCRYPT('RSA', 'The quick brown fox', @pub);
SET @plaintext = ASYMMETRIC_DECRYPT('RSA', @ciphertext, @priv);</pre><p>
            Suppose that:
          </p><pre data-lang="sql" class="programlisting">SET @s = a string to be encrypted
SET @priv = a valid private RSA key string in PEM format
SET @pub = the corresponding public RSA key string in PEM format</pre><p>
            Then these identity relationships hold:
          </p><pre data-lang="sql" class="programlisting">ASYMMETRIC_DECRYPT('RSA', ASYMMETRIC_ENCRYPT('RSA', @s, @priv), @pub) = @s
ASYMMETRIC_DECRYPT('RSA', ASYMMETRIC_ENCRYPT('RSA', @s, @pub), @priv) = @s</pre></li><li class="listitem"><a name="function_asymmetric-sign"></a><p>
            <a class="indexterm" name="idm46444319946944"></a>

            <a class="link" href="functions.html#function_asymmetric-sign"><code class="literal">ASYMMETRIC_SIGN(<em class="replaceable"><code>algorithm</code></em>,
            <em class="replaceable"><code>digest_str</code></em>,
            <em class="replaceable"><code>priv_key_str</code></em>,
            <em class="replaceable"><code>digest_type</code></em>)</code></a>
          </p><p>
            Signs a digest string using a private key string, and
            returns the signature as a binary string. If signing fails,
            the result is <code class="literal">NULL</code>.
          </p><p>
            <em class="replaceable"><code>digest_str</code></em> is the digest string.
            It can be generated by calling
            <a class="link" href="functions.html#function_create-digest"><code class="literal">CREATE_DIGEST()</code></a>.
            <em class="replaceable"><code>digest_type</code></em> indicates the digest
            algorithm used to generate the digest string.
          </p><p>
            <em class="replaceable"><code>priv_key_str</code></em> is the private key
            string to use for signing the digest string. It must be a
            valid key string in PEM format.
            <em class="replaceable"><code>algorithm</code></em> indicates the
            encryption algorithm used to create the key.
          </p><p>
            Supported <em class="replaceable"><code>algorithm</code></em> values:
            <code class="literal">'RSA'</code>, <code class="literal">'DSA'</code>
          </p><p>
            Supported <em class="replaceable"><code>digest_type</code></em> values:
            <code class="literal">'SHA224'</code>, <code class="literal">'SHA256'</code>,
            <code class="literal">'SHA384'</code>, <code class="literal">'SHA512'</code>
          </p><p>
            For a usage example, see the description of
            <a class="link" href="functions.html#function_asymmetric-verify"><code class="literal">ASYMMETRIC_VERIFY()</code></a>.
          </p></li><li class="listitem"><a name="function_asymmetric-verify"></a><p>
            <a class="indexterm" name="idm46444319925776"></a>

            <a class="link" href="functions.html#function_asymmetric-verify"><code class="literal">ASYMMETRIC_VERIFY(<em class="replaceable"><code>algorithm</code></em>,
            <em class="replaceable"><code>digest_str</code></em>,
            <em class="replaceable"><code>sig_str</code></em>,
            <em class="replaceable"><code>pub_key_str</code></em>,
            <em class="replaceable"><code>digest_type</code></em>)</code></a>
          </p><p>
            Verifies whether the signature string matches the digest
            string, and returns 1 or 0 to indicate whether verification
            succeeded or failed.
          </p><p>
            <em class="replaceable"><code>digest_str</code></em> is the digest string.
            It can be generated by calling
            <a class="link" href="functions.html#function_create-digest"><code class="literal">CREATE_DIGEST()</code></a>.
            <em class="replaceable"><code>digest_type</code></em> indicates the digest
            algorithm used to generate the digest string.
          </p><p>
            <em class="replaceable"><code>sig_str</code></em> is the signature string.
            It can be generated by calling
            <a class="link" href="functions.html#function_asymmetric-sign"><code class="literal">ASYMMETRIC_SIGN()</code></a>.
          </p><p>
            <em class="replaceable"><code>pub_key_str</code></em> is the public key
            string of the signer. It corresponds to the private key
            passed to <a class="link" href="functions.html#function_asymmetric-sign"><code class="literal">ASYMMETRIC_SIGN()</code></a>
            to generate the signature string and must be a valid key
            string in PEM format. <em class="replaceable"><code>algorithm</code></em>
            indicates the encryption algorithm used to create the key.
          </p><p>
            Supported <em class="replaceable"><code>algorithm</code></em> values:
            <code class="literal">'RSA'</code>, <code class="literal">'DSA'</code>
          </p><p>
            Supported <em class="replaceable"><code>digest_type</code></em> values:
            <code class="literal">'SHA224'</code>, <code class="literal">'SHA256'</code>,
            <code class="literal">'SHA384'</code>, <code class="literal">'SHA512'</code>
          </p><pre data-lang="sql" class="programlisting">-- Set the encryption algorithm and digest type
SET @algo = 'RSA';
SET @dig_type = 'SHA224';

-- Create private/public key pair
SET @priv = CREATE_ASYMMETRIC_PRIV_KEY(@algo, 1024);
SET @pub = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv);

-- Generate digest from string
SET @dig = CREATE_DIGEST(@dig_type, 'The quick brown fox');

-- Generate signature for digest and verify signature against digest
SET @sig = ASYMMETRIC_SIGN(@algo, @dig, @priv, @dig_type);
SET @verf = ASYMMETRIC_VERIFY(@algo, @dig, @sig, @pub, @dig_type);</pre></li><li class="listitem"><a name="function_create-asymmetric-priv-key"></a><p>
            <a class="indexterm" name="idm46444319901152"></a>

            <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY(<em class="replaceable"><code>algorithm</code></em>,
            {<em class="replaceable"><code>key_len</code></em>|<em class="replaceable"><code>dh_secret</code></em>})</code></a>
          </p><p>
            Creates a private key using the given algorithm and key
            length or DH secret, and returns the key as a binary string
            in PEM format. If key generation fails, the result is
            <code class="literal">NULL</code>.
          </p><p>
            Supported <em class="replaceable"><code>algorithm</code></em> values:
            <code class="literal">'RSA'</code>, <code class="literal">'DSA'</code>,
            <code class="literal">'DH'</code>
          </p><p>
            Supported <em class="replaceable"><code>key_len</code></em> values: The
            minimum key length in bits is 1,024. The maximum key length
            depends on the algorithm: 16,384 for RSA and 10,000 for DSA.
            These key-length limits are constraints imposed by OpenSSL.
            Server administrators can impose additional limits on
            maximum key length by setting environment variables. See
            <a class="xref" href="functions.html#enterprise-encryption-usage" title="12.19.2 MySQL Enterprise Encryption Usage and Examples">Section 12.19.2, “MySQL Enterprise Encryption Usage and Examples”</a>.
          </p><p>
            For DH keys, pass a shared DH secret instead of a key
            length. To create the secret, pass the key length to
            <a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS()</code></a>.
          </p><p>
            This example creates a 2,048-bit DSA private key, then
            derives a public key from the private key:
          </p><pre data-lang="sql" class="programlisting">SET @priv = CREATE_ASYMMETRIC_PRIV_KEY('DSA', 2048);
SET @pub = CREATE_ASYMMETRIC_PUB_KEY('DSA', @priv);</pre><p>
            For an example showing DH key generation, see the
            description of
            <a class="link" href="functions.html#function_asymmetric-derive"><code class="literal">ASYMMETRIC_DERIVE()</code></a>.
          </p><p>
            Some general considerations in choosing key lengths and
            encryption algorithms:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                The strength of encryption for private and public keys
                increases with the key size, but the time for key
                generation increases as well.
              </p></li><li class="listitem"><p>
                Generation of DH keys takes much longer than RSA or RSA
                keys.
              </p></li><li class="listitem"><p>
                Asymmetric encryption functions are slower than
                symmetric functions. If performance is an important
                factor and the functions are to be used very frequently,
                you are better off using symmetric encryption. For
                example, consider using
                <a class="link" href="functions.html#function_aes-encrypt"><code class="literal">AES_ENCRYPT()</code></a> and
                <a class="link" href="functions.html#function_aes-decrypt"><code class="literal">AES_DECRYPT()</code></a>.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_create-asymmetric-pub-key"></a><p>
            <a class="indexterm" name="idm46444319874608"></a>

            <a class="link" href="functions.html#function_create-asymmetric-pub-key"><code class="literal">CREATE_ASYMMETRIC_PUB_KEY(<em class="replaceable"><code>algorithm</code></em>,
            <em class="replaceable"><code>priv_key_str</code></em>)</code></a>
          </p><p>
            Derives a public key from the given private key using the
            given algorithm, and returns the key as a binary string in
            PEM format. If key derivation fails, the result is
            <code class="literal">NULL</code>.
          </p><p>
            <em class="replaceable"><code>priv_key_str</code></em> must be a valid key
            string in PEM format. <em class="replaceable"><code>algorithm</code></em>
            indicates the encryption algorithm used to create the key.
          </p><p>
            Supported <em class="replaceable"><code>algorithm</code></em> values:
            <code class="literal">'RSA'</code>, <code class="literal">'DSA'</code>,
            <code class="literal">'DH'</code>
          </p><p>
            For a usage example, see the description of
            <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>.
          </p></li><li class="listitem"><a name="function_create-dh-parameters"></a><p>
            <a class="indexterm" name="idm46444319859072"></a>

            <a class="link" href="functions.html#function_create-dh-parameters"><code class="literal">CREATE_DH_PARAMETERS(<em class="replaceable"><code>key_len</code></em>)</code></a>
          </p><p>
            Creates a shared secret for generating a DH private/public
            key pair and returns a binary string that can be passed to
            <a class="link" href="functions.html#function_create-asymmetric-priv-key"><code class="literal">CREATE_ASYMMETRIC_PRIV_KEY()</code></a>.
            If secret generation fails, the result is null.
          </p><p>
            Supported <em class="replaceable"><code>key_len</code></em> values: The
            minimum and maximum key lengths in bits are 1,024 and
            10,000. These key-length limits are constraints imposed by
            OpenSSL. Server administrators can impose additional limits
            on maximum key length by setting environment variables. See
            <a class="xref" href="functions.html#enterprise-encryption-usage" title="12.19.2 MySQL Enterprise Encryption Usage and Examples">Section 12.19.2, “MySQL Enterprise Encryption Usage and Examples”</a>.
          </p><p>
            For an example showing how to use the return value for
            generating symmetric keys, see the description of
            <a class="link" href="functions.html#function_asymmetric-derive"><code class="literal">ASYMMETRIC_DERIVE()</code></a>.
          </p><pre data-lang="sql" class="programlisting">SET @dhp = CREATE_DH_PARAMETERS(1024);</pre></li><li class="listitem"><a name="function_create-digest"></a><p>
            <a class="indexterm" name="idm46444319845776"></a>

            <a class="link" href="functions.html#function_create-digest"><code class="literal">CREATE_DIGEST(<em class="replaceable"><code>digest_type</code></em>,
            <em class="replaceable"><code>str</code></em>)</code></a>
          </p><p>
            Creates a digest from the given string using the given
            digest type, and returns the digest as a binary string. If
            digest generation fails, the result is
            <code class="literal">NULL</code>.
          </p><p>
            Supported <em class="replaceable"><code>digest_type</code></em> values:
            <code class="literal">'SHA224'</code>, <code class="literal">'SHA256'</code>,
            <code class="literal">'SHA384'</code>, <code class="literal">'SHA512'</code>
          </p><pre data-lang="sql" class="programlisting">SET @dig = CREATE_DIGEST('SHA512', The quick brown fox');</pre><p>
            The resulting digest string is suitable for use with
            <code class="literal">ASYMMETRIC_SIGN()</code> and
            <code class="literal">ASYMMETRIC_VERIFY()</code>.
</p></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="group-by-functions-and-modifiers"></a>12.20 Aggregate (GROUP BY) Functions</h2>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#group-by-functions">12.20.1 Aggregate (GROUP BY) Function Descriptions</a></span></dt><dt><span class="section"><a href="functions.html#group-by-modifiers">12.20.2 GROUP BY Modifiers</a></span></dt><dt><span class="section"><a href="functions.html#group-by-handling">12.20.3 MySQL Handling of GROUP BY</a></span></dt><dt><span class="section"><a href="functions.html#group-by-functional-dependence">12.20.4 Detection of Functional Dependence</a></span></dt></dl>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="group-by-functions"></a>12.20.1 Aggregate (GROUP BY) Function Descriptions</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444319829792"></a><a class="indexterm" name="idm46444319828752"></a><a class="indexterm" name="idm46444319827264"></a><p>
        This section describes group (aggregate) functions that operate
        on sets of values.
</p>
<div class="table">
<a name="idm46444319825248"></a><p class="title"><b>Table 12.26 Aggregate (GROUP BY) Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists aggregate (GROUP BY) functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_avg"><code class="literal">AVG()</code></a></td>
<td>
      Return the average value of the argument
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a></td>
<td>
      Return bitwise AND
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a></td>
<td>
      Return bitwise OR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a></td>
<td>
      Return bitwise XOR
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_count"><code class="literal">COUNT()</code></a></td>
<td>
      Return a count of the number of rows returned
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_count-distinct"><code class="literal">COUNT(DISTINCT)</code></a></td>
<td>
      Return the count of a number of different values
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_group-concat"><code class="literal">GROUP_CONCAT()</code></a></td>
<td>
      Return a concatenated string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-arrayagg"><code class="literal">JSON_ARRAYAGG()</code></a></td>
<td>
      Return result set as a single JSON array
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_json-objectagg"><code class="literal">JSON_OBJECTAGG()</code></a></td>
<td>
      Return result set as a single JSON object
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_max"><code class="literal">MAX()</code></a></td>
<td>
      Return the maximum value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_min"><code class="literal">MIN()</code></a></td>
<td>
      Return the minimum value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_std"><code class="literal">STD()</code></a></td>
<td>
      Return the population standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_stddev"><code class="literal">STDDEV()</code></a></td>
<td>
      Return the population standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_stddev-pop"><code class="literal">STDDEV_POP()</code></a></td>
<td>
      Return the population standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_stddev-samp"><code class="literal">STDDEV_SAMP()</code></a></td>
<td>
      Return the sample standard deviation
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a></td>
<td>
      Return the sum
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_var-pop"><code class="literal">VAR_POP()</code></a></td>
<td>
      Return the population standard variance
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_var-samp"><code class="literal">VAR_SAMP()</code></a></td>
<td>
      Return the sample variance
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_variance"><code class="literal">VARIANCE()</code></a></td>
<td>
      Return the population standard variance
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
        Unless otherwise stated, group functions ignore
        <code class="literal">NULL</code> values.
      </p><p>
        If you use a group function in a statement containing no
        <code class="literal">GROUP BY</code> clause, it is equivalent to grouping
        on all rows. For more information, see
        <a class="xref" href="functions.html#group-by-handling" title="12.20.3 MySQL Handling of GROUP BY">Section 12.20.3, “MySQL Handling of GROUP BY”</a>.
      </p><p>
        Most aggregate functions can be used as window functions. Those
        that can be used this way are signified in their syntax
        description by
        <code class="literal">[<em class="replaceable"><code>over_clause</code></em>]</code>,
        representing an optional <code class="literal">OVER</code> clause.
        <em class="replaceable"><code>over_clause</code></em> is described in
        <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>, which also includes
        other information about window function usage.
      </p><p>
        For numeric arguments, the variance and standard deviation
        functions return a <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a> value.
        The <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a> and
        <a class="link" href="functions.html#function_avg"><code class="literal">AVG()</code></a> functions return a
        <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> value for exact-value
        arguments (integer or <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a>),
        and a <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a> value for
        approximate-value arguments
        (<a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a> or
        <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a>).
      </p><p>
        The <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a> and
        <a class="link" href="functions.html#function_avg"><code class="literal">AVG()</code></a> aggregate functions do not
        work with temporal values. (They convert the values to numbers,
        losing everything after the first nonnumeric character.) To work
        around this problem, convert to numeric units, perform the
        aggregate operation, and convert back to a temporal value.
        Examples:
      </p><pre data-lang="sql" class="programlisting">SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(<em class="replaceable"><code>time_col</code></em>))) FROM <em class="replaceable"><code>tbl_name</code></em>;
SELECT FROM_DAYS(SUM(TO_DAYS(<em class="replaceable"><code>date_col</code></em>))) FROM <em class="replaceable"><code>tbl_name</code></em>;
</pre><p>
        Functions such as <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a> or
        <a class="link" href="functions.html#function_avg"><code class="literal">AVG()</code></a> that expect a numeric
        argument cast the argument to a number if necessary. For
        <a class="link" href="data-types.html#set" title="11.3.6 The SET Type"><code class="literal">SET</code></a> or
        <a class="link" href="data-types.html#enum" title="11.3.5 The ENUM Type"><code class="literal">ENUM</code></a> values, the cast operation
        causes the underlying numeric value to be used.
      </p><p>
        The <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a>,
        <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a>, and
        <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a> aggregate functions
        perform bit operations. Prior to MySQL 8.0, bit functions and
        operators required <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> (64-bit
        integer) arguments and returned
        <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> values, so they had a
        maximum range of 64 bits.
        Non-<a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> arguments were
        converted to <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> prior to
        performing the operation and truncation could occur.
      </p><p>
        In MySQL 8.0, bit functions and operators permit binary string
        type arguments (<a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">BINARY</code></a>,
        <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>, and the
        <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> types) and return a value of
        like type, which enables them to take arguments and produce
        return values larger than 64 bits. For discussion about argument
        evaluation and result types for bit operations, see the
        introductory discussion in <a class="xref" href="functions.html#bit-functions" title="12.12 Bit Functions and Operators">Section 12.12, “Bit Functions and Operators”</a>.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_avg"></a><p>
            <a class="indexterm" name="idm46444319710272"></a>

            <a class="indexterm" name="idm46444319709200"></a>

            <a class="indexterm" name="idm46444319708128"></a>

            <a class="link" href="functions.html#function_avg"><code class="literal">AVG([DISTINCT]
            <em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the average value of
            <code class="literal"><em class="replaceable"><code>expr</code></em></code>. The
            <code class="literal">DISTINCT</code> option can be used to return the
            average of the distinct values of
            <em class="replaceable"><code>expr</code></em>.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_avg"><code class="literal">AVG()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>; it cannot be used
            with <code class="literal">DISTINCT</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT student_name, AVG(test_score)</code></strong>
       <strong class="userinput"><code>FROM student</code></strong>
       <strong class="userinput"><code>GROUP BY student_name;</code></strong>
</pre></li><li class="listitem"><a name="function_bit-and"></a><p>
            <a class="indexterm" name="idm46444319689136"></a>

            <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the bitwise <code class="literal">AND</code> of all bits in
            <em class="replaceable"><code>expr</code></em>.
          </p><p>
            The result type depends on whether the function argument
            values are evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the argument values
                have a binary string type, and the argument is not a
                hexadecimal literal, bit literal, or
                <code class="literal">NULL</code> literal. Numeric evaluation
                occurs otherwise, with argument value conversion to
                unsigned 64-bit integers as necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the argument values. If argument values
                have unequal lengths, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
                error occurs. If the argument size exceeds 511 bytes, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_aggregate_operands_size"><code class="literal">ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE</code></a>
                error occurs. Numeric evaluation produces an unsigned
                64-bit integer.
</p></li></ul>
</div>
<p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_bit-and"><code class="literal">BIT_AND()</code></a> returns a neutral
            value (all bits set to 1) having the same length as the
            argument values.
          </p><p>
            <code class="literal">NULL</code> values do not affect the result
            unless all values are <code class="literal">NULL</code>. In that case,
            the result is a neutral value having the same length as the
            argument values.
          </p><p>
            For more information discussion about argument evaluation
            and result types, see the introductory discussion in
            <a class="xref" href="functions.html#bit-functions" title="12.12 Bit Functions and Operators">Section 12.12, “Bit Functions and Operators”</a>.
          </p><p>
            As of MySQL 8.0.12, this function executes as a window
            function if <em class="replaceable"><code>over_clause</code></em> is
            present. <em class="replaceable"><code>over_clause</code></em> is as
            described in <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_bit-or"></a><p>
            <a class="indexterm" name="idm46444319666640"></a>

            <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the bitwise <code class="literal">OR</code> of all bits in
            <em class="replaceable"><code>expr</code></em>.
          </p><p>
            The result type depends on whether the function argument
            values are evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the argument values
                have a binary string type, and the argument is not a
                hexadecimal literal, bit literal, or
                <code class="literal">NULL</code> literal. Numeric evaluation
                occurs otherwise, with argument value conversion to
                unsigned 64-bit integers as necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the argument values. If argument values
                have unequal lengths, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
                error occurs. If the argument size exceeds 511 bytes, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_aggregate_operands_size"><code class="literal">ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE</code></a>
                error occurs. Numeric evaluation produces an unsigned
                64-bit integer.
</p></li></ul>
</div>
<p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_bit-or"><code class="literal">BIT_OR()</code></a> returns a neutral
            value (all bits set to 0) having the same length as the
            argument values.
          </p><p>
            <code class="literal">NULL</code> values do not affect the result
            unless all values are <code class="literal">NULL</code>. In that case,
            the result is a neutral value having the same length as the
            argument values.
          </p><p>
            For more information discussion about argument evaluation
            and result types, see the introductory discussion in
            <a class="xref" href="functions.html#bit-functions" title="12.12 Bit Functions and Operators">Section 12.12, “Bit Functions and Operators”</a>.
          </p><p>
            As of MySQL 8.0.12, this function executes as a window
            function if <em class="replaceable"><code>over_clause</code></em> is
            present. <em class="replaceable"><code>over_clause</code></em> is as
            described in <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_bit-xor"></a><p>
            <a class="indexterm" name="idm46444319644144"></a>

            <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the bitwise <a class="link" href="functions.html#operator_xor"><code class="literal">XOR</code></a> of all
            bits in <em class="replaceable"><code>expr</code></em>.
          </p><p>
            The result type depends on whether the function argument
            values are evaluated as binary strings or numbers:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
                Binary-string evaluation occurs when the argument values
                have a binary string type, and the argument is not a
                hexadecimal literal, bit literal, or
                <code class="literal">NULL</code> literal. Numeric evaluation
                occurs otherwise, with argument value conversion to
                unsigned 64-bit integers as necessary.
              </p></li><li class="listitem"><p>
                Binary-string evaluation produces a binary string of the
                same length as the argument values. If argument values
                have unequal lengths, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_operands_size"><code class="literal">ER_INVALID_BITWISE_OPERANDS_SIZE</code></a>
                error occurs. If the argument size exceeds 511 bytes, an
                <a class="link" href="error-handling.html#error_er_invalid_bitwise_aggregate_operands_size"><code class="literal">ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE</code></a>
                error occurs. Numeric evaluation produces an unsigned
                64-bit integer.
</p></li></ul>
</div>
<p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_bit-xor"><code class="literal">BIT_XOR()</code></a> returns a neutral
            value (all bits set to 0) having the same length as the
            argument values.
          </p><p>
            <code class="literal">NULL</code> values do not affect the result
            unless all values are <code class="literal">NULL</code>. In that case,
            the result is a neutral value having the same length as the
            argument values.
          </p><p>
            For more information discussion about argument evaluation
            and result types, see the introductory discussion in
            <a class="xref" href="functions.html#bit-functions" title="12.12 Bit Functions and Operators">Section 12.12, “Bit Functions and Operators”</a>.
          </p><p>
            As of MySQL 8.0.12, this function executes as a window
            function if <em class="replaceable"><code>over_clause</code></em> is
            present. <em class="replaceable"><code>over_clause</code></em> is as
            described in <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_count"></a><p>
            <a class="indexterm" name="idm46444319621136"></a>

            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns a count of the number of non-<code class="literal">NULL</code>
            values of <em class="replaceable"><code>expr</code></em> in the rows
            retrieved by a <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a>
            statement. The result is a
            <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> value.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_count"><code class="literal">COUNT()</code></a> returns
            <code class="literal">0</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT student.student_name,COUNT(*)</code></strong>
       <strong class="userinput"><code>FROM student,course</code></strong>
       <strong class="userinput"><code>WHERE student.student_id=course.student_id</code></strong>
       <strong class="userinput"><code>GROUP BY student_name;</code></strong>
</pre><p>
            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(*)</code></a> is somewhat
            different in that it returns a count of the number of rows
            retrieved, whether or not they contain
            <code class="literal">NULL</code> values.
          </p><p>
            For transactional storage engines such as
            <code class="literal">InnoDB</code>, storing an exact row count is
            problematic. Multiple transactions may be occurring at the
            same time, each of which may affect the count.
          </p><p>
            <code class="literal">InnoDB</code> does not keep an internal count of
            rows in a table because concurrent transactions might
            <span class="quote">“<span class="quote">see</span>”</span> different numbers of rows at the same
            time. Consequently, <code class="literal">SELECT COUNT(*)</code>
            statements only count rows visible to the current
            transaction.
          </p><p>
            As of MySQL 8.0.13, <code class="literal">SELECT COUNT(*) FROM
            <em class="replaceable"><code>tbl_name</code></em></code> query
            performance for <code class="literal">InnoDB</code> tables is
            optimized for single-threaded workloads if there are no
            extra clauses such as <code class="literal">WHERE</code> or
            <code class="literal">GROUP BY</code>.
          </p><p>
            <code class="literal">InnoDB</code> processes <code class="literal">SELECT
            COUNT(*)</code> statements by traversing the smallest
            available secondary index unless an index or optimizer hint
            directs the optimizer to use a different index. If a
            secondary index is not present, <code class="literal">InnoDB</code>
            processes <code class="literal">SELECT COUNT(*)</code> statements by
            scanning the clustered index.
          </p><p>
            Processing <code class="literal">SELECT COUNT(*)</code> statements
            takes some time if index records are not entirely in the
            buffer pool. For a faster count, create a counter table and
            let your application update it according to the inserts and
            deletes it does. However, this method may not scale well in
            situations where thousands of concurrent transactions are
            initiating updates to the same counter table. If an
            approximate row count is sufficient, use
            <a class="link" href="sql-statements.html#show-table-status" title="13.7.7.36 SHOW TABLE STATUS Statement"><code class="literal">SHOW TABLE STATUS</code></a>.
          </p><p>
            <code class="literal">InnoDB</code> handles <code class="literal">SELECT
            COUNT(*)</code> and <code class="literal">SELECT COUNT(1)</code>
            operations in the same way. There is no performance
            difference.
          </p><p>
            For <code class="literal">MyISAM</code> tables,
            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(*)</code></a> is optimized to
            return very quickly if the
            <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> retrieves from one
            table, no other columns are retrieved, and there is no
            <code class="literal">WHERE</code> clause. For example:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COUNT(*) FROM student;</code></strong>
</pre><p>
            This optimization only applies to <code class="literal">MyISAM</code>
            tables, because an exact row count is stored for this
            storage engine and can be accessed very quickly.
            <code class="literal">COUNT(1)</code> is only subject to the same
            optimization if the first column is defined as <code class="literal">NOT
            NULL</code>.
          </p></li><li class="listitem"><a name="function_count-distinct"></a><p>
            <a class="indexterm" name="idm46444319571152"></a>

            <a class="indexterm" name="idm46444319570080"></a>

            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(DISTINCT
            <em class="replaceable"><code>expr</code></em>,[<em class="replaceable"><code>expr</code></em>...])</code></a>
          </p><p>
            Returns a count of the number of rows with different
            non-<code class="literal">NULL</code> <em class="replaceable"><code>expr</code></em>
            values.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(DISTINCT)</code></a> returns
            <code class="literal">0</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT COUNT(DISTINCT results) FROM student;</code></strong>
</pre><p>
            In MySQL, you can obtain the number of distinct expression
            combinations that do not contain <code class="literal">NULL</code> by
            giving a list of expressions. In standard SQL, you would
            have to do a concatenation of all expressions inside
            <a class="link" href="functions.html#function_count"><code class="literal">COUNT(DISTINCT ...)</code></a>.
          </p></li><li class="listitem"><a name="function_group-concat"></a><p>
            <a class="indexterm" name="idm46444319552832"></a>

            <a class="link" href="functions.html#function_group-concat"><code class="literal">GROUP_CONCAT(<em class="replaceable"><code>expr</code></em>)</code></a>
          </p><p>
            This function returns a string result with the concatenated
            non-<code class="literal">NULL</code> values from a group. It returns
            <code class="literal">NULL</code> if there are no
            non-<code class="literal">NULL</code> values. The full syntax is as
            follows:
          </p><pre data-lang="sql" class="programlisting">GROUP_CONCAT([DISTINCT] <em class="replaceable"><code>expr</code></em> [,<em class="replaceable"><code>expr</code></em> ...]
             [ORDER BY {<em class="replaceable"><code>unsigned_integer</code></em> | <em class="replaceable"><code>col_name</code></em> | <em class="replaceable"><code>expr</code></em>}
                 [ASC | DESC] [,<em class="replaceable"><code>col_name</code></em> ...]]
             [SEPARATOR <em class="replaceable"><code>str_val</code></em>])
</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT student_name,</code></strong>
         <strong class="userinput"><code>GROUP_CONCAT(test_score)</code></strong>
       <strong class="userinput"><code>FROM student</code></strong>
       <strong class="userinput"><code>GROUP BY student_name;</code></strong>
</pre><p>
            Or:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT student_name,</code></strong>
         <strong class="userinput"><code>GROUP_CONCAT(DISTINCT test_score</code></strong>
                      <strong class="userinput"><code>ORDER BY test_score DESC SEPARATOR ' ')</code></strong>
       <strong class="userinput"><code>FROM student</code></strong>
       <strong class="userinput"><code>GROUP BY student_name;</code></strong>
</pre><p>
            In MySQL, you can get the concatenated values of expression
            combinations. To eliminate duplicate values, use the
            <code class="literal">DISTINCT</code> clause. To sort values in the
            result, use the <code class="literal">ORDER BY</code> clause. To sort
            in reverse order, add the <code class="literal">DESC</code>
            (descending) keyword to the name of the column you are
            sorting by in the <code class="literal">ORDER BY</code> clause. The
            default is ascending order; this may be specified explicitly
            using the <code class="literal">ASC</code> keyword. The default
            separator between values in a group is comma
            (<code class="literal">,</code>). To specify a separator explicitly,
            use <code class="literal">SEPARATOR</code> followed by the string
            literal value that should be inserted between group values.
            To eliminate the separator altogether, specify
            <code class="literal">SEPARATOR ''</code>.
          </p><p>
            The result is truncated to the maximum length that is given
            by the <a class="link" href="server-administration.html#sysvar_group_concat_max_len"><code class="literal">group_concat_max_len</code></a>
            system variable, which has a default value of 1024. The
            value can be set higher, although the effective maximum
            length of the return value is constrained by the value of
            <a class="link" href="server-administration.html#sysvar_max_allowed_packet"><code class="literal">max_allowed_packet</code></a>. The
            syntax to change the value of
            <a class="link" href="server-administration.html#sysvar_group_concat_max_len"><code class="literal">group_concat_max_len</code></a> at
            runtime is as follows, where <em class="replaceable"><code>val</code></em>
            is an unsigned integer:
          </p><pre data-lang="sql" class="programlisting">SET [GLOBAL | SESSION] group_concat_max_len = <em class="replaceable"><code>val</code></em>;
</pre><p>
            The return value is a nonbinary or binary string, depending
            on whether the arguments are nonbinary or binary strings.
            The result type is <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">TEXT</code></a> or
            <a class="link" href="data-types.html#blob" title="11.3.4 The BLOB and TEXT Types"><code class="literal">BLOB</code></a> unless
            <a class="link" href="server-administration.html#sysvar_group_concat_max_len"><code class="literal">group_concat_max_len</code></a> is
            less than or equal to 512, in which case the result type is
            <a class="link" href="data-types.html#char" title="11.3.2 The CHAR and VARCHAR Types"><code class="literal">VARCHAR</code></a> or
            <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a>.
          </p><p>
            See also <a class="link" href="functions.html#function_concat"><code class="literal">CONCAT()</code></a> and
            <a class="link" href="functions.html#function_concat-ws"><code class="literal">CONCAT_WS()</code></a>:
            <a class="xref" href="functions.html#string-functions" title="12.7 String Functions and Operators">Section 12.7, “String Functions and Operators”</a>.
          </p></li><li class="listitem"><a name="function_json-arrayagg"></a><p>
            <a class="indexterm" name="idm46444319506000"></a>

            <a class="link" href="functions.html#function_json-arrayagg"><code class="literal">JSON_ARRAYAGG(<em class="replaceable"><code>col_or_expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Aggregates a result set as a single
            <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> array whose elements
            consist of the rows. The order of elements in this array is
            undefined. The function acts on a column or an expression
            that evaluates to a single value. Returns
            <code class="literal">NULL</code> if the result contains no rows, or
            in the event of an error.
          </p><p>
            As of MySQL 8.0.14, this function executes as a window
            function if <em class="replaceable"><code>over_clause</code></em> is
            present. <em class="replaceable"><code>over_clause</code></em> is as
            described in <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT o_id, attribute, value FROM t3;</code></strong>
+------+-----------+--------+
| o_id | attribute | value  |
+------+-----------+--------+
|    2 | color     | red    |
|    2 | fabric    | silk   |
|    3 | color     | green  |
|    3 | shape     | square |
+------+-----------+--------+
4 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT o_id, JSON_ARRAYAGG(attribute) AS attributes </code></strong>
       <strong class="userinput"><code>FROM t3 GROUP BY o_id;</code></strong>
+------+---------------------+
| o_id | attributes          |
+------+---------------------+
|    2 | ["color", "fabric"] |
|    3 | ["color", "shape"]  |
+------+---------------------+
2 rows in set (0.00 sec)
</pre></li><li class="listitem"><a name="function_json-objectagg"></a><p>
            <a class="indexterm" name="idm46444319488384"></a>

            <a class="link" href="functions.html#function_json-objectagg"><code class="literal">JSON_OBJECTAGG(<em class="replaceable"><code>key</code></em>,
            <em class="replaceable"><code>value</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Takes two column names or expressions as arguments, the
            first of these being used as a key and the second as a
            value, and returns a JSON object containing key-value pairs.
            Returns <code class="literal">NULL</code> if the result contains no
            rows, or in the event of an error. An error occurs if any
            key name is <code class="literal">NULL</code> or the number of
            arguments is not equal to 2.
          </p><p>
            As of MySQL 8.0.14, this function executes as a window
            function if <em class="replaceable"><code>over_clause</code></em> is
            present. <em class="replaceable"><code>over_clause</code></em> is as
            described in <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT o_id, attribute, value FROM t3;</code></strong>
+------+-----------+--------+
| o_id | attribute | value  |
+------+-----------+--------+
|    2 | color     | red    |
|    2 | fabric    | silk   |
|    3 | color     | green  |
|    3 | shape     | square |
+------+-----------+--------+
4 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT o_id, JSON_OBJECTAGG(attribute, value)</code></strong>
       <strong class="userinput"><code>FROM t3 GROUP BY o_id;</code></strong>
+------+---------------------------------------+
| o_id | JSON_OBJECTAGG(attribute, value)      |
+------+---------------------------------------+
|    2 | {"color": "red", "fabric": "silk"}    |
|    3 | {"color": "green", "shape": "square"} |
+------+---------------------------------------+
2 rows in set (0.00 sec)
</pre>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Duplicate key handling
</div>
<p>
              When the result of this function is normalized, values
              having duplicate keys are discarded. In keeping with the
              MySQL <a class="link" href="data-types.html#json" title="11.5 The JSON Data Type"><code class="literal">JSON</code></a> data type
              specification that does not permit duplicate keys, only
              the last value encountered is used with that key in the
              returned object (<span class="quote">“<span class="quote">last duplicate key wins</span>”</span>).
              This means that the result of using this function on
              columns from a <code class="literal">SELECT</code> can depend on the
              order in which in the rows are returned, which is not
              guaranteed. When used as a window function, if there are
              duplicate keys within a frame, only the last value for the
              key is present in the result. The value for the key from
              last row in the frame is deterministic if the
              <code class="literal">ORDER BY</code> specification guarantees that
              the values have a specific order. If not, the resulting
              value of the key is nondeterministic. Consider the
              following:
</p>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE t(c VARCHAR(10), i INT);</code></strong>
Query OK, 0 rows affected (0.03 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES</code></strong>
       <strong class="userinput"><code>('key', 3), ('key', 4), ('key', 5);</code></strong>
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT c, i FROM t;</code></strong>
+------+------+
| c    | i    |
+------+------+
| key  |    3 |
| key  |    4 |
| key  |    5 |
+------+------+
3 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i) FROM t;</code></strong>
+----------------------+
| JSON_OBJECTAGG(c, i) |
+----------------------+
| {"key": 5}           |
+----------------------+
1 row in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>DELETE FROM t;</code></strong>
Query OK, 3 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES</code></strong>
       <strong class="userinput"><code>('key', 3), ('key', 5), ('key', 4);</code></strong>
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>SELECT c, i FROM t;</code></strong>
+------+------+
| c    | i    |
+------+------+
| key  |    3 |
| key  |    5 |
| key  |    4 |
+------+------+
3 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i) FROM t;</code></strong>
+----------------------+
| JSON_OBJECTAGG(c, i) |
+----------------------+
| {"key": 4}           |
+----------------------+
1 row in set (0.00 sec)
</pre><p>
            The key chosen from the last query is nondeterministic. If
            you prefer a particular key ordering, you can invoke
            <code class="literal">JSON_OBJECTAGG()</code> as a window function by
            including an <code class="literal">OVER</code> clause with an
            <code class="literal">ORDER BY</code> specification to impose a
            particular order on frame rows. The following examples show
            what happens with and without <code class="literal">ORDER BY</code>
            for a few different frame specifications.
          </p><p>
            Without <code class="literal">ORDER BY</code>, the frame is the entire
            partition:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i)</code></strong>
       <strong class="userinput"><code>OVER () AS json_object FROM t;</code></strong>
+-------------+
| json_object |
+-------------+
| {"key": 4}  |
| {"key": 4}  |
| {"key": 4}  |
+-------------+
</pre><p>
            With <code class="literal">ORDER BY</code>, where the frame is the
            default of <code class="literal">RANGE BETWEEN UNBOUNDED PRECEDING AND
            CURRENT ROW</code> (in both ascending and descending
            order):
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i)</code></strong>
       <strong class="userinput"><code>OVER (ORDER BY i) AS json_object FROM t;</code></strong>
+-------------+
| json_object |
+-------------+
| {"key": 3}  |
| {"key": 4}  |
| {"key": 5}  |
+-------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i)</code></strong>
       <strong class="userinput"><code>OVER (ORDER BY i DESC) AS json_object FROM t;</code></strong>
+-------------+
| json_object |
+-------------+
| {"key": 5}  |
| {"key": 4}  |
| {"key": 3}  |
+-------------+
</pre><p>
            With <code class="literal">ORDER BY</code> and an explicit frame of
            the entire partition:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i)</code></strong>
       <strong class="userinput"><code>OVER (ORDER BY i</code></strong>
            <strong class="userinput"><code>ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)</code></strong>
        <strong class="userinput"><code>AS json_object</code></strong>
       <strong class="userinput"><code>FROM t;</code></strong>
+-------------+
| json_object |
+-------------+
| {"key": 5}  |
| {"key": 5}  |
| {"key": 5}  |
+-------------+
</pre><p>
            To return a particular key value (such as the smallest or
            largest), include a <code class="literal">LIMIT</code> clause in the
            appropriate query. For example:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i)</code></strong>
       <strong class="userinput"><code>OVER (ORDER BY i) AS json_object FROM t LIMIT 1;</code></strong>
+-------------+
| json_object |
+-------------+
| {"key": 3}  |
+-------------+
mysql&gt; <strong class="userinput"><code>SELECT JSON_OBJECTAGG(c, i)</code></strong>
       <strong class="userinput"><code>OVER (ORDER BY i DESC) AS json_object FROM t LIMIT 1;</code></strong>
+-------------+
| json_object |
+-------------+
| {"key": 5}  |
+-------------+
</pre><p>
            See <a class="xref" href="data-types.html#json-normalization" title="Normalization, Merging, and Autowrapping of JSON Values">Normalization, Merging, and Autowrapping of JSON Values</a>, for additional
            information and examples.
          </p></li><li class="listitem"><a name="function_max"></a><p>
            <a class="indexterm" name="idm46444319430208"></a>

            <a class="indexterm" name="idm46444319429136"></a>

            <a class="indexterm" name="idm46444319428064"></a>

            <a class="link" href="functions.html#function_max"><code class="literal">MAX([DISTINCT]
            <em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the maximum value of
            <em class="replaceable"><code>expr</code></em>.
            <a class="link" href="functions.html#function_max"><code class="literal">MAX()</code></a> may take a string
            argument; in such cases, it returns the maximum string
            value. See <a class="xref" href="optimization.html#mysql-indexes" title="8.3.1 How MySQL Uses Indexes">Section 8.3.1, “How MySQL Uses Indexes”</a>. The
            <code class="literal">DISTINCT</code> keyword can be used to find the
            maximum of the distinct values of
            <em class="replaceable"><code>expr</code></em>, however, this produces the
            same result as omitting <code class="literal">DISTINCT</code>.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_max"><code class="literal">MAX()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>; it cannot be used
            with <code class="literal">DISTINCT</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT student_name, MIN(test_score), MAX(test_score)</code></strong>
       <strong class="userinput"><code>FROM student</code></strong>
       <strong class="userinput"><code>GROUP BY student_name;</code></strong>
</pre><p>
            For <a class="link" href="functions.html#function_max"><code class="literal">MAX()</code></a>, MySQL currently
            compares <a class="link" href="data-types.html#enum" title="11.3.5 The ENUM Type"><code class="literal">ENUM</code></a> and
            <a class="link" href="data-types.html#set" title="11.3.6 The SET Type"><code class="literal">SET</code></a> columns by their string
            value rather than by the string's relative position in the
            set. This differs from how <code class="literal">ORDER BY</code>
            compares them.
          </p></li><li class="listitem"><a name="function_min"></a><p>
            <a class="indexterm" name="idm46444319401104"></a>

            <a class="indexterm" name="idm46444319400032"></a>

            <a class="indexterm" name="idm46444319398960"></a>

            <a class="link" href="functions.html#function_min"><code class="literal">MIN([DISTINCT]
            <em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the minimum value of
            <em class="replaceable"><code>expr</code></em>.
            <a class="link" href="functions.html#function_min"><code class="literal">MIN()</code></a> may take a string
            argument; in such cases, it returns the minimum string
            value. See <a class="xref" href="optimization.html#mysql-indexes" title="8.3.1 How MySQL Uses Indexes">Section 8.3.1, “How MySQL Uses Indexes”</a>. The
            <code class="literal">DISTINCT</code> keyword can be used to find the
            minimum of the distinct values of
            <em class="replaceable"><code>expr</code></em>, however, this produces the
            same result as omitting <code class="literal">DISTINCT</code>.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_min"><code class="literal">MIN()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>; it cannot be used
            with <code class="literal">DISTINCT</code>.
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT student_name, MIN(test_score), MAX(test_score)</code></strong>
       <strong class="userinput"><code>FROM student</code></strong>
       <strong class="userinput"><code>GROUP BY student_name;</code></strong>
</pre><p>
            For <a class="link" href="functions.html#function_min"><code class="literal">MIN()</code></a>, MySQL currently
            compares <a class="link" href="data-types.html#enum" title="11.3.5 The ENUM Type"><code class="literal">ENUM</code></a> and
            <a class="link" href="data-types.html#set" title="11.3.6 The SET Type"><code class="literal">SET</code></a> columns by their string
            value rather than by the string's relative position in the
            set. This differs from how <code class="literal">ORDER BY</code>
            compares them.
          </p></li><li class="listitem"><a name="function_std"></a><p>
            <a class="indexterm" name="idm46444319372000"></a>

            <a class="link" href="functions.html#function_std"><code class="literal">STD(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the population standard deviation of
            <em class="replaceable"><code>expr</code></em>.
            <a class="link" href="functions.html#function_std"><code class="literal">STD()</code></a> is a synonym for the
            standard SQL function
            <a class="link" href="functions.html#function_stddev-pop"><code class="literal">STDDEV_POP()</code></a>, provided as a
            MySQL extension.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_std"><code class="literal">STD()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_stddev"></a><p>
            <a class="indexterm" name="idm46444319356096"></a>

            <a class="indexterm" name="idm46444319355024"></a>

            <a class="indexterm" name="idm46444319353952"></a>

            <a class="link" href="functions.html#function_stddev"><code class="literal">STDDEV(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the population standard deviation of
            <em class="replaceable"><code>expr</code></em>.
            <a class="link" href="functions.html#function_stddev"><code class="literal">STDDEV()</code></a> is a synonym for the
            standard SQL function
            <a class="link" href="functions.html#function_stddev-pop"><code class="literal">STDDEV_POP()</code></a>, provided for
            compatibility with Oracle.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_stddev"><code class="literal">STDDEV()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_stddev-pop"></a><p>
            <a class="indexterm" name="idm46444319338320"></a>

            <a class="link" href="functions.html#function_stddev-pop"><code class="literal">STDDEV_POP(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the population standard deviation of
            <em class="replaceable"><code>expr</code></em> (the square root of
            <a class="link" href="functions.html#function_var-pop"><code class="literal">VAR_POP()</code></a>). You can also use
            <a class="link" href="functions.html#function_std"><code class="literal">STD()</code></a> or
            <a class="link" href="functions.html#function_stddev"><code class="literal">STDDEV()</code></a>, which are
            equivalent but not standard SQL.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_stddev-pop"><code class="literal">STDDEV_POP()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_stddev-samp"></a><p>
            <a class="indexterm" name="idm46444319321888"></a>

            <a class="link" href="functions.html#function_stddev-samp"><code class="literal">STDDEV_SAMP(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the sample standard deviation of
            <em class="replaceable"><code>expr</code></em> (the square root of
            <a class="link" href="functions.html#function_var-samp"><code class="literal">VAR_SAMP()</code></a>.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_stddev-samp"><code class="literal">STDDEV_SAMP()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_sum"></a><p>
            <a class="indexterm" name="idm46444319307376"></a>

            <a class="indexterm" name="idm46444319306304"></a>

            <a class="indexterm" name="idm46444319305232"></a>

            <a class="link" href="functions.html#function_sum"><code class="literal">SUM([DISTINCT]
            <em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the sum of <em class="replaceable"><code>expr</code></em>. If the
            return set has no rows, <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a>
            returns <code class="literal">NULL</code>. The
            <code class="literal">DISTINCT</code> keyword can be used to sum only
            the distinct values of <em class="replaceable"><code>expr</code></em>.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>; it cannot be used
            with <code class="literal">DISTINCT</code>.
          </p></li><li class="listitem"><a name="function_var-pop"></a><p>
            <a class="indexterm" name="idm46444319288240"></a>

            <a class="link" href="functions.html#function_var-pop"><code class="literal">VAR_POP(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the population standard variance of
            <em class="replaceable"><code>expr</code></em>. It considers rows as the
            whole population, not as a sample, so it has the number of
            rows as the denominator. You can also use
            <a class="link" href="functions.html#function_variance"><code class="literal">VARIANCE()</code></a>, which is
            equivalent but is not standard SQL.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_var-pop"><code class="literal">VAR_POP()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_var-samp"></a><p>
            <a class="indexterm" name="idm46444319274160"></a>

            <a class="link" href="functions.html#function_var-samp"><code class="literal">VAR_SAMP(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the sample variance of
            <em class="replaceable"><code>expr</code></em>. That is, the denominator is
            the number of rows minus one.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_var-samp"><code class="literal">VAR_SAMP()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_variance"></a><p>
            <a class="indexterm" name="idm46444319261440"></a>

            <a class="link" href="functions.html#function_variance"><code class="literal">VARIANCE(<em class="replaceable"><code>expr</code></em>)
            [<em class="replaceable"><code>over_clause</code></em>]</code></a>
          </p><p>
            Returns the population standard variance of
            <em class="replaceable"><code>expr</code></em>.
            <a class="link" href="functions.html#function_variance"><code class="literal">VARIANCE()</code></a> is a synonym for
            the standard SQL function
            <a class="link" href="functions.html#function_var-pop"><code class="literal">VAR_POP()</code></a>, provided as a
            MySQL extension.
          </p><p>
            If there are no matching rows,
            <a class="link" href="functions.html#function_variance"><code class="literal">VARIANCE()</code></a> returns
            <code class="literal">NULL</code>.
          </p><p>
            This function executes as a window function if
            <em class="replaceable"><code>over_clause</code></em> is present.
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="group-by-modifiers"></a>12.20.2 GROUP BY Modifiers</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444319247104"></a><a class="indexterm" name="idm46444319246032"></a><a class="indexterm" name="idm46444319244960"></a><a class="indexterm" name="idm46444319243888"></a><a class="indexterm" name="idm46444319242400"></a><p>
        The <code class="literal">GROUP BY</code> clause permits a <code class="literal">WITH
        ROLLUP</code> modifier that causes summary output to include
        extra rows that represent higher-level (that is,
        super-aggregate) summary operations. <code class="literal">ROLLUP</code>
        thus enables you to answer questions at multiple levels of
        analysis with a single query. For example,
        <code class="literal">ROLLUP</code> can be used to provide support for
        OLAP (Online Analytical Processing) operations.
      </p><p>
        Suppose that a <code class="literal">sales</code> table has
        <code class="literal">year</code>, <code class="literal">country</code>,
        <code class="literal">product</code>, and <code class="literal">profit</code>
        columns for recording sales profitability:
      </p><pre data-lang="sql" class="programlisting">CREATE TABLE sales
(
    year    INT,
    country VARCHAR(20),
    product VARCHAR(32),
    profit  INT
);</pre><p>
        To summarize table contents per year, use a simple
        <code class="literal">GROUP BY</code> like this:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year;</code></strong>
+------+--------+
| year | profit |
+------+--------+
| 2000 |   4525 |
| 2001 |   3010 |
+------+--------+
</pre><p>
        The output shows the total (aggregate) profit for each year. To
        also determine the total profit summed over all years, you must
        add up the individual values yourself or run an additional
        query. Or you can use <code class="literal">ROLLUP</code>, which provides
        both levels of analysis with a single query. Adding a
        <code class="literal">WITH ROLLUP</code> modifier to the <code class="literal">GROUP
        BY</code> clause causes the query to produce another
        (super-aggregate) row that shows the grand total over all year
        values:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year WITH ROLLUP;</code></strong>
+------+--------+
| year | profit |
+------+--------+
| 2000 |   4525 |
| 2001 |   3010 |
| NULL |   7535 |
+------+--------+
</pre><p>
        The <code class="literal">NULL</code> value in the <code class="literal">year</code>
        column identifies the grand total super-aggregate line.
      </p><p>
        <code class="literal">ROLLUP</code> has a more complex effect when there
        are multiple <code class="literal">GROUP BY</code> columns. In this case,
        each time there is a change in value in any but the last
        grouping column, the query produces an extra super-aggregate
        summary row.
      </p><p>
        For example, without <code class="literal">ROLLUP</code>, a summary of the
        <code class="literal">sales</code> table based on <code class="literal">year</code>,
        <code class="literal">country</code>, and <code class="literal">product</code> might
        look like this, where the output indicates summary values only
        at the year/country/product level of analysis:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, country, product, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year, country, product;</code></strong>
+------+---------+------------+--------+
| year | country | product    | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer   |   1500 |
| 2000 | Finland | Phone      |    100 |
| 2000 | India   | Calculator |    150 |
| 2000 | India   | Computer   |   1200 |
| 2000 | USA     | Calculator |     75 |
| 2000 | USA     | Computer   |   1500 |
| 2001 | Finland | Phone      |     10 |
| 2001 | USA     | Calculator |     50 |
| 2001 | USA     | Computer   |   2700 |
| 2001 | USA     | TV         |    250 |
+------+---------+------------+--------+
</pre><p>
        With <code class="literal">ROLLUP</code> added, the query produces several
        extra rows:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, country, product, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year, country, product WITH ROLLUP;</code></strong>
+------+---------+------------+--------+
| year | country | product    | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer   |   1500 |
| 2000 | Finland | Phone      |    100 |
| 2000 | Finland | NULL       |   1600 |
| 2000 | India   | Calculator |    150 |
| 2000 | India   | Computer   |   1200 |
| 2000 | India   | NULL       |   1350 |
| 2000 | USA     | Calculator |     75 |
| 2000 | USA     | Computer   |   1500 |
| 2000 | USA     | NULL       |   1575 |
| 2000 | NULL    | NULL       |   4525 |
| 2001 | Finland | Phone      |     10 |
| 2001 | Finland | NULL       |     10 |
| 2001 | USA     | Calculator |     50 |
| 2001 | USA     | Computer   |   2700 |
| 2001 | USA     | TV         |    250 |
| 2001 | USA     | NULL       |   3000 |
| 2001 | NULL    | NULL       |   3010 |
| NULL | NULL    | NULL       |   7535 |
+------+---------+------------+--------+
</pre><p>
        Now the output includes summary information at four levels of
        analysis, not just one:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            Following each set of product rows for a given year and
            country, an extra super-aggregate summary row appears
            showing the total for all products. These rows have the
            <code class="literal">product</code> column set to
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            Following each set of rows for a given year, an extra
            super-aggregate summary row appears showing the total for
            all countries and products. These rows have the
            <code class="literal">country</code> and <code class="literal">products</code>
            columns set to <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            Finally, following all other rows, an extra super-aggregate
            summary row appears showing the grand total for all years,
            countries, and products. This row has the
            <code class="literal">year</code>, <code class="literal">country</code>, and
            <code class="literal">products</code> columns set to
            <code class="literal">NULL</code>.
</p></li></ul>
</div>
<p>
        The <code class="literal">NULL</code> indicators in each super-aggregate
        row are produced when the row is sent to the client. The server
        looks at the columns named in the <code class="literal">GROUP BY</code>
        clause following the leftmost one that has changed value. For
        any column in the result set with a name that matches any of
        those names, its value is set to <code class="literal">NULL</code>. (If
        you specify grouping columns by column position, the server
        identifies which columns to set to <code class="literal">NULL</code> by
        position.)
      </p><p>
        Because the <code class="literal">NULL</code> values in the
        super-aggregate rows are placed into the result set at such a
        late stage in query processing, you can test them as
        <code class="literal">NULL</code> values only in the select list or
        <code class="literal">HAVING</code> clause. You cannot test them as
        <code class="literal">NULL</code> values in join conditions or the
        <code class="literal">WHERE</code> clause to determine which rows to
        select. For example, you cannot add <code class="literal">WHERE product IS
        NULL</code> to the query to eliminate from the output all but
        the super-aggregate rows.
      </p><p>
        The <code class="literal">NULL</code> values do appear as
        <code class="literal">NULL</code> on the client side and can be tested as
        such using any MySQL client programming interface. However, at
        this point, you cannot distinguish whether a
        <code class="literal">NULL</code> represents a regular grouped value or a
        super-aggregate value. To test the distinction, use the
        <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> function, described
        later.
      </p><p>
        Previously, MySQL did not allow the use of
        <code class="literal">DISTINCT</code> or <code class="literal">ORDER BY</code> in a
        query having a <code class="literal">WITH ROLLUP</code> option. This
        restriction is lifted in MySQL 8.0.12 and later. (Bug #87450,
        Bug #86311, Bug #26640100, Bug #26073513)
      </p><p>
        For <code class="literal">GROUP BY ... WITH ROLLUP</code> queries, to test
        whether <code class="literal">NULL</code> values in the result represent
        super-aggregate values, the
        <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> function is available
        for use in the select list, <code class="literal">HAVING</code> clause,
        and (as of MySQL 8.0.12) <code class="literal">ORDER BY</code> clause. For
        example, <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING(year)</code></a> returns 1
        when <code class="literal">NULL</code> in the <code class="literal">year</code>
        column occurs in a super-aggregate row, and 0 otherwise.
        Similarly, <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING(country)</code></a> and
        <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING(product)</code></a> return 1 for
        super-aggregate <code class="literal">NULL</code> values in the
        <code class="literal">country</code> and <code class="literal">product</code>
        columns, respectively:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>year, country, product, SUM(profit) AS profit,</code></strong>
         <strong class="userinput"><code>GROUPING(year) AS grp_year,</code></strong>
         <strong class="userinput"><code>GROUPING(country) AS grp_country,</code></strong>
         <strong class="userinput"><code>GROUPING(product) AS grp_product</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year, country, product WITH ROLLUP;</code></strong>
+------+---------+------------+--------+----------+-------------+-------------+
| year | country | product    | profit | grp_year | grp_country | grp_product |
+------+---------+------------+--------+----------+-------------+-------------+
| 2000 | Finland | Computer   |   1500 |        0 |           0 |           0 |
| 2000 | Finland | Phone      |    100 |        0 |           0 |           0 |
| 2000 | Finland | NULL       |   1600 |        0 |           0 |           1 |
| 2000 | India   | Calculator |    150 |        0 |           0 |           0 |
| 2000 | India   | Computer   |   1200 |        0 |           0 |           0 |
| 2000 | India   | NULL       |   1350 |        0 |           0 |           1 |
| 2000 | USA     | Calculator |     75 |        0 |           0 |           0 |
| 2000 | USA     | Computer   |   1500 |        0 |           0 |           0 |
| 2000 | USA     | NULL       |   1575 |        0 |           0 |           1 |
| 2000 | NULL    | NULL       |   4525 |        0 |           1 |           1 |
| 2001 | Finland | Phone      |     10 |        0 |           0 |           0 |
| 2001 | Finland | NULL       |     10 |        0 |           0 |           1 |
| 2001 | USA     | Calculator |     50 |        0 |           0 |           0 |
| 2001 | USA     | Computer   |   2700 |        0 |           0 |           0 |
| 2001 | USA     | TV         |    250 |        0 |           0 |           0 |
| 2001 | USA     | NULL       |   3000 |        0 |           0 |           1 |
| 2001 | NULL    | NULL       |   3010 |        0 |           1 |           1 |
| NULL | NULL    | NULL       |   7535 |        1 |           1 |           1 |
+------+---------+------------+--------+----------+-------------+-------------+
</pre><p>
        Instead of displaying the
        <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> results directly, you
        can use <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> to substitute
        labels for super-aggregate <code class="literal">NULL</code> values:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>IF(GROUPING(year), 'All years', year) AS year,</code></strong>
         <strong class="userinput"><code>IF(GROUPING(country), 'All countries', country) AS country,</code></strong>
         <strong class="userinput"><code>IF(GROUPING(product), 'All products', product) AS product,</code></strong>
         <strong class="userinput"><code>SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year, country, product WITH ROLLUP;</code></strong>
+-----------+---------------+--------------+--------+
| year      | country       | product      | profit |
+-----------+---------------+--------------+--------+
| 2000      | Finland       | Computer     |   1500 |
| 2000      | Finland       | Phone        |    100 |
| 2000      | Finland       | All products |   1600 |
| 2000      | India         | Calculator   |    150 |
| 2000      | India         | Computer     |   1200 |
| 2000      | India         | All products |   1350 |
| 2000      | USA           | Calculator   |     75 |
| 2000      | USA           | Computer     |   1500 |
| 2000      | USA           | All products |   1575 |
| 2000      | All countries | All products |   4525 |
| 2001      | Finland       | Phone        |     10 |
| 2001      | Finland       | All products |     10 |
| 2001      | USA           | Calculator   |     50 |
| 2001      | USA           | Computer     |   2700 |
| 2001      | USA           | TV           |    250 |
| 2001      | USA           | All products |   3000 |
| 2001      | All countries | All products |   3010 |
| All years | All countries | All products |   7535 |
+-----------+---------------+--------------+--------+
</pre><p>
        With multiple expression arguments,
        <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> returns a result
        representing a bitmask the combines the results for each
        expression, with the lowest-order bit corresponding to the
        result for the rightmost expression. For example,
        <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING(year, country, product)</code></a>
        is evaluated like this:
      </p><pre data-lang="clike" class="programlisting">  result for GROUPING(<em class="replaceable"><code>product</code></em>)
+ result for GROUPING(<em class="replaceable"><code>country</code></em>) &lt;&lt; 1
+ result for GROUPING(<em class="replaceable"><code>year</code></em>) &lt;&lt; 2
</pre><p>
        The result of such a <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>
        is nonzero if any of the expressions represents a
        super-aggregate <code class="literal">NULL</code>, so you can return only
        the super-aggregate rows and filter out the regular grouped rows
        like this:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, country, product, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year, country, product WITH ROLLUP</code></strong>
       <strong class="userinput"><code>HAVING GROUPING(year, country, product) &lt;&gt; 0;</code></strong>
+------+---------+---------+--------+
| year | country | product | profit |
+------+---------+---------+--------+
| 2000 | Finland | NULL    |   1600 |
| 2000 | India   | NULL    |   1350 |
| 2000 | USA     | NULL    |   1575 |
| 2000 | NULL    | NULL    |   4525 |
| 2001 | Finland | NULL    |     10 |
| 2001 | USA     | NULL    |   3000 |
| 2001 | NULL    | NULL    |   3010 |
| NULL | NULL    | NULL    |   7535 |
+------+---------+---------+--------+
</pre><p>
        The <code class="literal">sales</code> table contains no
        <code class="literal">NULL</code> values, so all <code class="literal">NULL</code>
        values in a <code class="literal">ROLLUP</code> result represent
        super-aggregate values. When the data set contains
        <code class="literal">NULL</code> values, <code class="literal">ROLLUP</code>
        summaries may contain <code class="literal">NULL</code> values not only in
        super-aggregate rows, but also in regular grouped rows.
        <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> enables these to be
        distinguished. Suppose that table <code class="literal">t1</code> contains
        a simple data set with two grouping factors for a set of
        quantity values, where <code class="literal">NULL</code> indicates
        something like <span class="quote">“<span class="quote">other</span>”</span> or <span class="quote">“<span class="quote">unknown</span>”</span>:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM t1;</code></strong>
+------+-------+----------+
| name | size  | quantity |
+------+-------+----------+
| ball | small |       10 |
| ball | large |       20 |
| ball | NULL  |        5 |
| hoop | small |       15 |
| hoop | large |        5 |
| hoop | NULL  |        3 |
+------+-------+----------+
</pre><p>
        A simple <code class="literal">ROLLUP</code> operation produces these
        results, in which it is not so easy to distinguish
        <code class="literal">NULL</code> values in super-aggregate rows from
        <code class="literal">NULL</code> values in regular grouped rows:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT name, size, SUM(quantity) AS quantity</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP;</code></strong>
+------+-------+----------+
| name | size  | quantity |
+------+-------+----------+
| ball | NULL  |        5 |
| ball | large |       20 |
| ball | small |       10 |
| ball | NULL  |       35 |
| hoop | NULL  |        3 |
| hoop | large |        5 |
| hoop | small |       15 |
| hoop | NULL  |       23 |
| NULL | NULL  |       58 |
+------+-------+----------+
</pre><p>
        Using <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> to substitute
        labels for the super-aggregate <code class="literal">NULL</code> values
        makes the result easier to interpret:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>IF(GROUPING(name) = 1, 'All items', name) AS name,</code></strong>
         <strong class="userinput"><code>IF(GROUPING(size) = 1, 'All sizes', size) AS size,</code></strong>
         <strong class="userinput"><code>SUM(quantity) AS quantity</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP;</code></strong>
+-----------+-----------+----------+
| name      | size      | quantity |
+-----------+-----------+----------+
| ball      | NULL      |        5 |
| ball      | large     |       20 |
| ball      | small     |       10 |
| ball      | All sizes |       35 |
| hoop      | NULL      |        3 |
| hoop      | large     |        5 |
| hoop      | small     |       15 |
| hoop      | All sizes |       23 |
| All items | All sizes |       58 |
+-----------+-----------+----------+
</pre>
<div class="simplesect">

<div class="titlepage">
<div>

<div class="simple">
<h4 class="title"><a name="group-by-modifiers-other-considerations-when-using-rollup"></a>Other Considerations When using ROLLUP</h4>
</div>
</div>
</div>
<p>
          The following discussion lists some behaviors specific to the
          MySQL implementation of <code class="literal">ROLLUP</code>.
        </p><p>
          Prior to MySQL 8.0.12, when you use <code class="literal">ROLLUP</code>,
          you cannot also use an <code class="literal">ORDER BY</code> clause to
          sort the results. In other words, <code class="literal">ROLLUP</code>
          and <code class="literal">ORDER BY</code> were mutually exclusive in
          MySQL. However, you still have some control over sort order.
          To work around the restriction that prevents using
          <code class="literal">ROLLUP</code> with <code class="literal">ORDER BY</code> and
          achieve a specific sort order of grouped results, generate the
          grouped result set as a derived table and apply <code class="literal">ORDER
          BY</code> to it. For example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM</code></strong>
         <strong class="userinput"><code>(SELECT year, SUM(profit) AS profit</code></strong>
         <strong class="userinput"><code>FROM sales GROUP BY year WITH ROLLUP) AS dt</code></strong>
       <strong class="userinput"><code>ORDER BY year DESC;</code></strong>
+------+--------+
| year | profit |
+------+--------+
| 2001 |   3010 |
| 2000 |   4525 |
| NULL |   7535 |
+------+--------+
</pre><p>
          As of MySQL 8.0.12, <code class="literal">ORDER BY</code> and
          <code class="literal">ROLLUP</code> can be used together, which enables
          the use of <code class="literal">ORDER BY</code> and
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> to achieve a
          specific sort order of grouped results. For example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year WITH ROLLUP</code></strong>
       <strong class="userinput"><code>ORDER BY GROUPING(year) DESC;</code></strong>
+------+--------+
| year | profit |
+------+--------+
| NULL |   7535 |
| 2000 |   4525 |
| 2001 |   3010 |
+------+--------+
</pre><p>
          In both cases, the super-aggregate summary rows sort with the
          rows from which they are calculated, and their placement
          depends on sort order (at the end for ascending sort, at the
          beginning for descending sort).
        </p><p>
          <code class="literal">LIMIT</code> can be used to restrict the number of
          rows returned to the client. <code class="literal">LIMIT</code> is
          applied after <code class="literal">ROLLUP</code>, so the limit applies
          against the extra rows added by <code class="literal">ROLLUP</code>. For
          example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, country, product, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year, country, product WITH ROLLUP</code></strong>
       <strong class="userinput"><code>LIMIT 5;</code></strong>
+------+---------+------------+--------+
| year | country | product    | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer   |   1500 |
| 2000 | Finland | Phone      |    100 |
| 2000 | Finland | NULL       |   1600 |
| 2000 | India   | Calculator |    150 |
| 2000 | India   | Computer   |   1200 |
+------+---------+------------+--------+
</pre><p>
          Using <code class="literal">LIMIT</code> with <code class="literal">ROLLUP</code>
          may produce results that are more difficult to interpret,
          because there is less context for understanding the
          super-aggregate rows.
        </p><p>
          A MySQL extension permits a column that does not appear in the
          <code class="literal">GROUP BY</code> list to be named in the select
          list. (For information about nonaggregated columns and
          <code class="literal">GROUP BY</code>, see
          <a class="xref" href="functions.html#group-by-handling" title="12.20.3 MySQL Handling of GROUP BY">Section 12.20.3, “MySQL Handling of GROUP BY”</a>.) In this case, the server
          is free to choose any value from this nonaggregated column in
          summary rows, and this includes the extra rows added by
          <code class="literal">WITH ROLLUP</code>. For example, in the following
          query, <code class="literal">country</code> is a nonaggregated column
          that does not appear in the <code class="literal">GROUP BY</code> list
          and values chosen for this column are nondeterministic:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, country, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year WITH ROLLUP;</code></strong>
+------+---------+--------+
| year | country | profit |
+------+---------+--------+
| 2000 | India   |   4525 |
| 2001 | USA     |   3010 |
| NULL | USA     |   7535 |
+------+---------+--------+
</pre><p>
          This behavior is permitted when the
          <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> SQL mode
          is not enabled. If that mode is enabled, the server rejects
          the query as illegal because <code class="literal">country</code> is not
          listed in the <code class="literal">GROUP BY</code> clause. With
          <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> enabled,
          you can still execute the query by using the
          <code class="literal">ANY_VALUE()</code> function for
          nondeterministic-value columns:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT year, ANY_VALUE(country) AS country, SUM(profit) AS profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY year WITH ROLLUP;</code></strong>
+------+---------+--------+
| year | country | profit |
+------+---------+--------+
| 2000 | India   |   4525 |
| 2001 | USA     |   3010 |
| NULL | USA     |   7535 |
+------+---------+--------+
</pre>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="group-by-handling"></a>12.20.3 MySQL Handling of GROUP BY</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444319062192"></a><a class="indexterm" name="idm46444319061152"></a><a class="indexterm" name="idm46444319059648"></a><a class="indexterm" name="idm46444319058160"></a><p>
        SQL-92 and earlier does not permit queries for which the select
        list, <code class="literal">HAVING</code> condition, or <code class="literal">ORDER
        BY</code> list refer to nonaggregated columns that are not
        named in the <code class="literal">GROUP BY</code> clause. For example,
        this query is illegal in standard SQL-92 because the
        nonaggregated <code class="literal">name</code> column in the select list
        does not appear in the <code class="literal">GROUP BY</code>:
      </p><pre data-lang="sql" class="programlisting">SELECT o.custid, c.name, MAX(o.payment)
  FROM orders AS o, customers AS c
  WHERE o.custid = c.custid
  GROUP BY o.custid;</pre><p>
        For the query to be legal in SQL-92, the <code class="literal">name</code>
        column must be omitted from the select list or named in the
        <code class="literal">GROUP BY</code> clause.
      </p><p>
        SQL:1999 and later permits such nonaggregates per optional
        feature T301 if they are functionally dependent on
        <code class="literal">GROUP BY</code> columns: If such a relationship
        exists between <code class="literal">name</code> and
        <code class="literal">custid</code>, the query is legal. This would be the
        case, for example, were <code class="literal">custid</code> a primary key
        of <code class="literal">customers</code>.
      </p><p>
        MySQL implements detection of functional dependence. If the
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> SQL mode is
        enabled (which it is by default), MySQL rejects queries for
        which the select list, <code class="literal">HAVING</code> condition, or
        <code class="literal">ORDER BY</code> list refer to nonaggregated columns
        that are neither named in the <code class="literal">GROUP BY</code> clause
        nor are functionally dependent on them.
      </p><p>
        MySQL also permits a nonaggregate column not named in a
        <code class="literal">GROUP BY</code> clause when SQL
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> mode is
        enabled, provided that this column is limited to a single value,
        as shown in the following example:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE mytable (</code></strong>
    -&gt;    <strong class="userinput"><code>id INT UNSIGNED NOT NULL PRIMARY KEY,</code></strong>
    -&gt;    <strong class="userinput"><code>a VARCHAR(10),</code></strong>
    -&gt;    <strong class="userinput"><code>b INT</code></strong>
    -&gt; <strong class="userinput"><code>);</code></strong>

mysql&gt; <strong class="userinput"><code>INSERT INTO mytable</code></strong>
    -&gt; <strong class="userinput"><code>VALUES (1, 'abc', 1000),</code></strong>
    -&gt;        <strong class="userinput"><code>(2, 'abc', 2000),</code></strong>
    -&gt;        <strong class="userinput"><code>(3, 'def', 4000);</code></strong>

mysql&gt; <strong class="userinput"><code>SET SESSION sql_mode = sys.list_add(@@session.sql_mode, 'ONLY_FULL_GROUP_BY');</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT a, SUM(b) FROM mytable WHERE a = 'abc';</code></strong>
+------+--------+
| a    | SUM(b) |
+------+--------+
| abc  |   3000 |
+------+--------+
</pre><p>
        It is also possible to have more than one nonaggregate column in
        the <a class="link" href="sql-statements.html#select" title="13.2.10 SELECT Statement"><code class="literal">SELECT</code></a> list when employing
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a>. In this
        case, every such column must be limited to a single value in the
        <code class="literal">WHERE</code> clause, and all such limiting
        conditions must be joined by logical <code class="literal">AND</code>, as
        shown here:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>DROP TABLE IF EXISTS mytable;</code></strong>

mysql&gt; <strong class="userinput"><code>CREATE TABLE mytable (</code></strong>
    -&gt;    <strong class="userinput"><code>id INT UNSIGNED NOT NULL PRIMARY KEY,</code></strong>
    -&gt;    <strong class="userinput"><code>a VARCHAR(10),</code></strong>
    -&gt;    <strong class="userinput"><code>b VARCHAR(10),</code></strong>
    -&gt;    <strong class="userinput"><code>c INT</code></strong>
    -&gt; <strong class="userinput"><code>);</code></strong>

mysql&gt; <strong class="userinput"><code>INSERT INTO mytable</code></strong>
    -&gt; <strong class="userinput"><code>VALUES (1, 'abc', 'qrs', 1000),</code></strong>
    -&gt;        <strong class="userinput"><code>(2, 'abc', 'tuv', 2000),</code></strong>
    -&gt;        <strong class="userinput"><code>(3, 'def', 'qrs', 4000),</code></strong>
    -&gt;        <strong class="userinput"><code>(4, 'def', 'tuv', 8000),</code></strong>
    -&gt;        <strong class="userinput"><code>(5, 'abc', 'qrs', 16000),</code></strong>
    -&gt;        <strong class="userinput"><code>(6, 'def', 'tuv', 32000);</code></strong>

mysql&gt; <strong class="userinput"><code>SELECT @@session.sql_mode;</code></strong>
+---------------------------------------------------------------+
| @@session.sql_mode                                            |
+---------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+---------------------------------------------------------------+

mysql&gt; <strong class="userinput"><code>SELECT a, b, SUM(c) FROM mytable</code></strong>
    -&gt;     <strong class="userinput"><code>WHERE a = 'abc' AND b = 'qrs';</code></strong>
+------+------+--------+
| a    | b    | SUM(c) |
+------+------+--------+
| abc  | qrs  |  17000 |
+------+------+--------+
</pre><p>
        If <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> is
        disabled, a MySQL extension to the standard SQL use of
        <code class="literal">GROUP BY</code> permits the select list,
        <code class="literal">HAVING</code> condition, or <code class="literal">ORDER
        BY</code> list to refer to nonaggregated columns even if the
        columns are not functionally dependent on <code class="literal">GROUP
        BY</code> columns. This causes MySQL to accept the preceding
        query. In this case, the server is free to choose any value from
        each group, so unless they are the same, the values chosen are
        nondeterministic, which is probably not what you want.
        Furthermore, the selection of values from each group cannot be
        influenced by adding an <code class="literal">ORDER BY</code> clause.
        Result set sorting occurs after values have been chosen, and
        <code class="literal">ORDER BY</code> does not affect which value within
        each group the server chooses. Disabling
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> is useful
        primarily when you know that, due to some property of the data,
        all values in each nonaggregated column not named in the
        <code class="literal">GROUP BY</code> are the same for each group.
      </p><p>
        You can achieve the same effect without disabling
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> by using
        <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> to refer to the
        nonaggregated column.
      </p><p>
        The following discussion demonstrates functional dependence, the
        error message MySQL produces when functional dependence is
        absent, and ways of causing MySQL to accept a query in the
        absence of functional dependence.
      </p><p>
        This query might be invalid with
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> enabled
        because the nonaggregated <code class="literal">address</code> column in
        the select list is not named in the <code class="literal">GROUP BY</code>
        clause:
      </p><pre data-lang="sql" class="programlisting">SELECT name, address, MAX(age) FROM t GROUP BY name;</pre><p>
        The query is valid if <code class="literal">name</code> is a primary key
        of <code class="literal">t</code> or is a unique <code class="literal">NOT
        NULL</code> column. In such cases, MySQL recognizes that the
        selected column is functionally dependent on a grouping column.
        For example, if <code class="literal">name</code> is a primary key, its
        value determines the value of <code class="literal">address</code> because
        each group has only one value of the primary key and thus only
        one row. As a result, there is no randomness in the choice of
        <code class="literal">address</code> value in a group and no need to
        reject the query.
      </p><p>
        The query is invalid if <code class="literal">name</code> is not a primary
        key of <code class="literal">t</code> or a unique <code class="literal">NOT
        NULL</code> column. In this case, no functional dependency
        can be inferred and an error occurs:
      </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT name, address, MAX(age) FROM t GROUP BY name;</code></strong>
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP
BY clause and contains nonaggregated column 'mydb.t.address' which
is not functionally dependent on columns in GROUP BY clause; this
is incompatible with sql_mode=only_full_group_by
</pre><p>
        If you know that, <span class="emphasis"><em>for a given data set,</em></span>
        each <code class="literal">name</code> value in fact uniquely determines
        the <code class="literal">address</code> value, <code class="literal">address</code>
        is effectively functionally dependent on
        <code class="literal">name</code>. To tell MySQL to accept the query, you
        can use the <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> function:
      </p><pre data-lang="sql" class="programlisting">SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;</pre><p>
        Alternatively, disable
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a>.
      </p><p>
        The preceding example is quite simple, however. In particular,
        it is unlikely you would group on a single primary key column
        because every group would contain only one row. For addtional
        examples demonstrating functional dependence in more complex
        queries, see <a class="xref" href="functions.html#group-by-functional-dependence" title="12.20.4 Detection of Functional Dependence">Section 12.20.4, “Detection of Functional Dependence”</a>.
      </p><p>
        If a query has aggregate functions and no <code class="literal">GROUP
        BY</code> clause, it cannot have nonaggregated columns in the
        select list, <code class="literal">HAVING</code> condition, or
        <code class="literal">ORDER BY</code> list with
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> enabled:
      </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT name, MAX(age) FROM t;</code></strong>
ERROR 1140 (42000): In aggregated query without GROUP BY, expression
#1 of SELECT list contains nonaggregated column 'mydb.t.name'; this
is incompatible with sql_mode=only_full_group_by
</pre><p>
        Without <code class="literal">GROUP BY</code>, there is a single group and
        it is nondeterministic which <code class="literal">name</code> value to
        choose for the group. Here, too,
        <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> can be used, if it is
        immaterial which <code class="literal">name</code> value MySQL chooses:
      </p><pre data-lang="sql" class="programlisting">SELECT ANY_VALUE(name), MAX(age) FROM t;</pre><p>
        <code class="literal">ONLY_FULL_GROUP_BY</code> also affects handling of
        queries that use <code class="literal">DISTINCT</code> and <code class="literal">ORDER
        BY</code>. Consider the case of a table <code class="literal">t</code>
        with three columns <code class="literal">c1</code>, <code class="literal">c2</code>,
        and <code class="literal">c3</code> that contains these rows:
      </p><pre data-lang="none" class="programlisting">c1 c2 c3
1  2  A
3  4  B
1  2  C</pre><p>
        Suppose that we execute the following query, expecting the
        results to be ordered by <code class="literal">c3</code>:
      </p><pre data-lang="sql" class="programlisting">SELECT DISTINCT c1, c2 FROM t ORDER BY c3;</pre><p>
        To order the result, duplicates must be eliminated first. But to
        do so, should we keep the first row or the third? This arbitrary
        choice influences the retained value of <code class="literal">c3</code>,
        which in turn influences ordering and makes it arbitrary as
        well. To prevent this problem, a query that has
        <code class="literal">DISTINCT</code> and <code class="literal">ORDER BY</code> is
        rejected as invalid if any <code class="literal">ORDER BY</code>
        expression does not satisfy at least one of these conditions:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            The expression is equal to one in the select list
          </p></li><li class="listitem"><p>
            All columns referenced by the expression and belonging to
            the query's selected tables are elements of the select list
</p></li></ul>
</div>
<p>
        Another MySQL extension to standard SQL permits references in
        the <code class="literal">HAVING</code> clause to aliased expressions in
        the select list. For example, the following query returns
        <code class="literal">name</code> values that occur only once in table
        <code class="literal">orders</code>:
      </p><pre data-lang="sql" class="programlisting">SELECT name, COUNT(name) FROM orders
  GROUP BY name
  HAVING COUNT(name) = 1;</pre><p>
        The MySQL extension permits the use of an alias in the
        <code class="literal">HAVING</code> clause for the aggregated column:
      </p><pre data-lang="sql" class="programlisting">SELECT name, COUNT(name) AS c FROM orders
  GROUP BY name
  HAVING c = 1;</pre><a class="indexterm" name="idm46444318944080"></a><a class="indexterm" name="idm46444318942592"></a><a class="indexterm" name="idm46444318941104"></a><a class="indexterm" name="idm46444318940032"></a><p>
        Standard SQL permits only column expressions in <code class="literal">GROUP
        BY</code> clauses, so a statement such as this is invalid
        because <code class="literal">FLOOR(value/100)</code> is a noncolumn
        expression:
      </p><pre data-lang="sql" class="programlisting">SELECT id, FLOOR(value/100)
  FROM <em class="replaceable"><code>tbl_name</code></em>
  GROUP BY id, FLOOR(value/100);
</pre><p>
        MySQL extends standard SQL to permit noncolumn expressions in
        <code class="literal">GROUP BY</code> clauses and considers the preceding
        statement valid.
      </p><p>
        Standard SQL also does not permit aliases in <code class="literal">GROUP
        BY</code> clauses. MySQL extends standard SQL to permit
        aliases, so another way to write the query is as follows:
      </p><pre data-lang="sql" class="programlisting">SELECT id, FLOOR(value/100) AS val
  FROM <em class="replaceable"><code>tbl_name</code></em>
  GROUP BY id, val;
</pre><p>
        The alias <code class="literal">val</code> is considered a column
        expression in the <code class="literal">GROUP BY</code> clause.
      </p><p>
        In the presence of a noncolumn expression in the <code class="literal">GROUP
        BY</code> clause, MySQL recognizes equality between that
        expression and expressions in the select list. This means that
        with <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> SQL
        mode enabled, the query containing <code class="literal">GROUP BY id,
        FLOOR(value/100)</code> is valid because that same
        <a class="link" href="functions.html#function_floor"><code class="literal">FLOOR()</code></a> expression occurs in the
        select list. However, MySQL does not try to recognize functional
        dependence on <code class="literal">GROUP BY</code> noncolumn expressions,
        so the following query is invalid with
        <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> enabled,
        even though the third selected expression is a simple formula of
        the <code class="literal">id</code> column and the
        <a class="link" href="functions.html#function_floor"><code class="literal">FLOOR()</code></a> expression in the
        <code class="literal">GROUP BY</code> clause:
      </p><pre data-lang="sql" class="programlisting">SELECT id, FLOOR(value/100), id+FLOOR(value/100)
  FROM <em class="replaceable"><code>tbl_name</code></em>
  GROUP BY id, FLOOR(value/100);
</pre><p>
        A workaround is to use a derived table:
      </p><pre data-lang="sql" class="programlisting">SELECT id, F, id+F
  FROM
    (SELECT id, FLOOR(value/100) AS F
     FROM <em class="replaceable"><code>tbl_name</code></em>
     GROUP BY id, FLOOR(value/100)) AS dt;
</pre>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="group-by-functional-dependence"></a>12.20.4 Detection of Functional Dependence</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444318915248"></a><p>
        The following discussion provides several examples of the ways
        in which MySQL detects functional dependencies. The examples use
        this notation:
      </p><pre data-lang="sql" class="programlisting">{<em class="replaceable"><code>X</code></em>} -&gt; {<em class="replaceable"><code>Y</code></em>}
</pre><p>
        Understand this as <span class="quote">“<span class="quote"><em class="replaceable"><code>X</code></em> uniquely
        determines <em class="replaceable"><code>Y</code></em>,</span>”</span> which also
        means that <em class="replaceable"><code>Y</code></em> is functionally
        dependent on <em class="replaceable"><code>X</code></em>.
      </p><p>
        The examples use the <code class="literal">world</code> database, which
        can be downloaded from
        <a class="ulink" href="https://dev.mysql.com/doc/index-other.html" target="_top">https://dev.mysql.com/doc/index-other.html</a>. You can find details
        on how to install the database on the same page.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><a class="xref" href="functions.html#functional-dependence-keys" title="Functional Dependencies Derived from Keys">Functional Dependencies Derived from Keys</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#functional-dependence-multiple-column-keys" title="Functional Dependencies Derived from Multiple-Column Keys and from Equalities">Functional Dependencies Derived from Multiple-Column Keys and from
Equalities</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#functional-dependence-special-cases" title="Functional Dependency Special Cases">Functional Dependency Special Cases</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#functional-dependence-views" title="Functional Dependencies and Views">Functional Dependencies and Views</a></p></li><li class="listitem"><p><a class="xref" href="functions.html#functional-dependence-combinations" title="Combinations of Functional Dependencies">Combinations of Functional Dependencies</a></p></li></ul>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="functional-dependence-keys"></a>Functional Dependencies Derived from Keys</h4>

</div>

</div>

</div>
<p>
          The following query selects, for each country, a count of
          spoken languages:
        </p><pre data-lang="sql" class="programlisting">SELECT co.Name, COUNT(*)
FROM countrylanguage cl, country co
WHERE cl.CountryCode = co.Code
GROUP BY co.Code;</pre><p>
          <code class="literal">co.Code</code> is a primary key of
          <code class="literal">co</code>, so all columns of <code class="literal">co</code>
          are functionally dependent on it, as expressed using this
          notation:
        </p><pre data-lang="sql" class="programlisting">{co.Code} -&gt; {co.*}</pre><p>
          Thus, <code class="literal">co.name</code> is functionally dependent on
          <code class="literal">GROUP BY</code> columns and the query is valid.
        </p><p>
          A <code class="literal">UNIQUE</code> index over a <code class="literal">NOT
          NULL</code> column could be used instead of a primary key
          and the same functional dependence would apply. (This is not
          true for a <code class="literal">UNIQUE</code> index that permits
          <code class="literal">NULL</code> values because it permits multiple
          <code class="literal">NULL</code> values and in that case uniqueness is
          lost.)
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="functional-dependence-multiple-column-keys"></a>Functional Dependencies Derived from Multiple-Column Keys and from
Equalities</h4>
</div>
</div>
</div>
<p>
          This query selects, for each country, a list of all spoken
          languages and how many people speak them:
        </p><pre data-lang="sql" class="programlisting">SELECT co.Name, cl.Language,
cl.Percentage * co.Population / 100.0 AS SpokenBy
FROM countrylanguage cl, country co
WHERE cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;</pre><p>
          The pair (<code class="literal">cl.CountryCode</code>,
          <code class="literal">cl.Language</code>) is a two-column composite
          primary key of <code class="literal">cl</code>, so that column pair
          uniquely determines all columns of <code class="literal">cl</code>:
        </p><pre data-lang="sql" class="programlisting">{cl.CountryCode, cl.Language} -&gt; {cl.*}</pre><p>
          Moreover, because of the equality in the
          <code class="literal">WHERE</code> clause:
        </p><pre data-lang="sql" class="programlisting">{cl.CountryCode} -&gt; {co.Code}</pre><p>
          And, because <code class="literal">co.Code</code> is primary key of
          <code class="literal">co</code>:
        </p><pre data-lang="sql" class="programlisting">{co.Code} -&gt; {co.*}</pre><p>
          <span class="quote">“<span class="quote">Uniquely determines</span>”</span> relationships are
          transitive, therefore:
        </p><pre data-lang="sql" class="programlisting">{cl.CountryCode, cl.Language} -&gt; {cl.*,co.*}</pre><p>
          As a result, the query is valid.
        </p><p>
          As with the previous example, a <code class="literal">UNIQUE</code> key
          over <code class="literal">NOT NULL</code> columns could be used instead
          of a primary key.
        </p><p>
          An <code class="literal">INNER JOIN</code> condition can be used instead
          of <code class="literal">WHERE</code>. The same functional dependencies
          apply:
        </p><pre data-lang="sql" class="programlisting">SELECT co.Name, cl.Language,
cl.Percentage * co.Population/100.0 AS SpokenBy
FROM countrylanguage cl INNER JOIN country co
ON cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="functional-dependence-special-cases"></a>Functional Dependency Special Cases</h4>

</div>

</div>

</div>
<p>
          Whereas an equality test in a <code class="literal">WHERE</code>
          condition or <code class="literal">INNER JOIN</code> condition is
          symmetric, an equality test in an outer join condition is not,
          because tables play different roles.
        </p><p>
          Assume that referential integrity has been accidentally broken
          and there exists a row of <code class="literal">countrylanguage</code>
          without a corresponding row in <code class="literal">country</code>.
          Consider the same query as in the previous example, but with a
          <code class="literal">LEFT JOIN</code>:
        </p><pre data-lang="sql" class="programlisting">SELECT co.Name, cl.Language,
cl.Percentage * co.Population/100.0 AS SpokenBy
FROM countrylanguage cl LEFT JOIN country co
ON cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;</pre><p>
          For a given value of <code class="literal">cl.CountryCode</code>, the
          value of <code class="literal">co.Code</code> in the join result is
          either found in a matching row (determined by
          <code class="literal">cl.CountryCode</code>) or is
          <code class="literal">NULL</code>-complemented if there is no match
          (also determined by <code class="literal">cl.CountryCode</code>). In
          each case, this relationship applies:
        </p><pre data-lang="sql" class="programlisting">{cl.CountryCode} -&gt; {co.Code}</pre><p>
          <code class="literal">cl.CountryCode</code> is itself functionally
          dependent on {<code class="literal">cl.CountryCode</code>,
          <code class="literal">cl.Language</code>} which is a primary key.
        </p><p>
          If in the join result <code class="literal">co.Code</code> is
          <code class="literal">NULL</code>-complemented,
          <code class="literal">co.Name</code> is as well. If
          <code class="literal">co.Code</code> is not
          <code class="literal">NULL</code>-complemented, then because
          <code class="literal">co.Code</code> is a primary key, it determines
          <code class="literal">co.Name</code>. Therefore, in all cases:
        </p><pre data-lang="sql" class="programlisting">{co.Code} -&gt; {co.Name}</pre><p>
          Which yields:
        </p><pre data-lang="sql" class="programlisting">{cl.CountryCode, cl.Language} -&gt; {cl.*,co.*}</pre><p>
          As a result, the query is valid.
        </p><p>
          However, suppose that the tables are swapped, as in this
          query:
        </p><pre data-lang="sql" class="programlisting">SELECT co.Name, cl.Language,
cl.Percentage * co.Population/100.0 AS SpokenBy
FROM country co LEFT JOIN countrylanguage cl
ON cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;</pre><p>
          Now this relationship does <span class="emphasis"><em>not</em></span> apply:
        </p><pre data-lang="sql" class="programlisting">{cl.CountryCode, cl.Language} -&gt; {cl.*,co.*}</pre><p>
          Indeed, all <code class="literal">NULL</code>-complemented rows made for
          <code class="literal">cl</code> will be put into a single group (they
          have both <code class="literal">GROUP BY</code> columns equal to
          <code class="literal">NULL</code>), and inside this group the value of
          <code class="literal">co.Name</code> can vary. The query is invalid and
          MySQL rejects it.
        </p><p>
          Functional dependence in outer joins is thus linked to whether
          determinant columns belong to the left or right side of the
          <code class="literal">LEFT JOIN</code>. Determination of functional
          dependence becomes more complex if there are nested outer
          joins or the join condition does not consist entirely of
          equality comparisons.
</p>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="functional-dependence-views"></a>Functional Dependencies and Views</h4>

</div>

</div>

</div>
<p>
          Suppose that a view on countries produces their code, their
          name in uppercase, and how many different official languages
          they have:
        </p><pre data-lang="sql" class="programlisting">CREATE VIEW Country2 AS
SELECT co.Code, UPPER(co.Name) AS UpperName,
COUNT(cl.Language) AS OfficialLanguages
FROM country AS co JOIN countrylanguage AS cl
ON cl.CountryCode = co.Code
WHERE cl.isOfficial = 'T'
GROUP BY co.Code;</pre><p>
          This definition is valid because:
        </p><pre data-lang="sql" class="programlisting">{co.Code} -&gt; {co.*}</pre><p>
          In the view result, the first selected column is
          <code class="literal">co.Code</code>, which is also the group column and
          thus determines all other selected expressions:
        </p><pre data-lang="sql" class="programlisting">{Country2.Code} -&gt; {Country2.*}</pre><p>
          MySQL understands this and uses this information, as described
          following.
        </p><p>
          This query displays countries, how many different official
          languages they have, and how many cities they have, by joining
          the view with the <code class="literal">city</code> table:
        </p><pre data-lang="sql" class="programlisting">SELECT co2.Code, co2.UpperName, co2.OfficialLanguages,
COUNT(*) AS Cities
FROM country2 AS co2 JOIN city ci
ON ci.CountryCode = co2.Code
GROUP BY co2.Code;</pre><p>
          This query is valid because, as seen previously:
        </p><pre data-lang="sql" class="programlisting">{co2.Code} -&gt; {co2.*}</pre><p>
          MySQL is able to discover a functional dependency in the
          result of a view and use that to validate a query which uses
          the view. The same would be true if
          <code class="literal">country2</code> were a derived table (or common
          table expression), as in:
        </p><pre data-lang="sql" class="programlisting">SELECT co2.Code, co2.UpperName, co2.OfficialLanguages,
COUNT(*) AS Cities
FROM
(
 SELECT co.Code, UPPER(co.Name) AS UpperName,
 COUNT(cl.Language) AS OfficialLanguages
 FROM country AS co JOIN countrylanguage AS cl
 ON cl.CountryCode=co.Code
 WHERE cl.isOfficial='T'
 GROUP BY co.Code
) AS co2
JOIN city ci ON ci.CountryCode = co2.Code
GROUP BY co2.Code;</pre>
</div>
<div class="simplesect">
<div class="titlepage">
<div>
<div class="simple">
<h4 class="title"><a name="functional-dependence-combinations"></a>Combinations of Functional Dependencies</h4>

</div>

</div>

</div>
<p>
          MySQL is able to combine all of the preceding types of
          functional dependencies (key based, equality based, view
          based) to validate more complex queries.
</p>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="window-functions"></a>12.21 Window Functions</h2>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#window-function-descriptions">12.21.1 Window Function Descriptions</a></span></dt><dt><span class="section"><a href="functions.html#window-functions-usage">12.21.2 Window Function Concepts and Syntax</a></span></dt><dt><span class="section"><a href="functions.html#window-functions-frames">12.21.3 Window Function Frame Specification</a></span></dt><dt><span class="section"><a href="functions.html#window-functions-named-windows">12.21.4 Named Windows</a></span></dt><dt><span class="section"><a href="functions.html#window-function-restrictions">12.21.5 Window Function Restrictions</a></span></dt></dl>
</div>
<a class="indexterm" name="idm46444318820768"></a><p>
      MySQL supports window functions that, for each row from a query,
      perform a calculation using rows related to that row. The
      following sections discuss how to use window functions, including
      descriptions of the <code class="literal">OVER</code> and
      <code class="literal">WINDOW</code> clauses. The first section provides
      descriptions of the nonaggregate window functions. For
      descriptions of the aggregate window functions, see
      <a class="xref" href="functions.html#group-by-functions" title="12.20.1 Aggregate (GROUP BY) Function Descriptions">Section 12.20.1, “Aggregate (GROUP BY) Function Descriptions”</a>.
    </p><p>
      For information about optimization and window functions, see
      <a class="xref" href="optimization.html#window-function-optimization" title="8.2.1.21 Window Function Optimization">Section 8.2.1.21, “Window Function Optimization”</a>.
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="window-function-descriptions"></a>12.21.1 Window Function Descriptions</h3>
</div>
</div>
</div>
<p>
        This section describes nonaggregate window functions that, for
        each row from a query, perform a calculation using rows related
        to that row. Most aggregate functions also can be used as window
        functions; see <a class="xref" href="functions.html#group-by-functions" title="12.20.1 Aggregate (GROUP BY) Function Descriptions">Section 12.20.1, “Aggregate (GROUP BY) Function Descriptions”</a>.
      </p><p>
        For window function usage information and examples, and
        definitions of terms such as the <code class="literal">OVER</code> clause,
        window, partition, frame, and peer, see
        <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
</p>
<div class="table">
<a name="idm46444318811152"></a><p class="title"><b>Table 12.27 Window Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists window functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_cume-dist"><code class="literal">CUME_DIST()</code></a></td>
<td>
      Cumulative distribution value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_dense-rank"><code class="literal">DENSE_RANK()</code></a></td>
<td>
      Rank of current row within its partition, without gaps
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_first-value"><code class="literal">FIRST_VALUE()</code></a></td>
<td>
      Value of argument from first row of window frame
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a></td>
<td>
      Value of argument from row lagging current row within partition
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_last-value"><code class="literal">LAST_VALUE()</code></a></td>
<td>
      Value of argument from last row of window frame
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a></td>
<td>
      Value of argument from row leading current row within partition
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_nth-value"><code class="literal">NTH_VALUE()</code></a></td>
<td>
      Value of argument from N-th row of window frame
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ntile"><code class="literal">NTILE()</code></a></td>
<td>
      Bucket number of current row within its partition.
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_percent-rank"><code class="literal">PERCENT_RANK()</code></a></td>
<td>
      Percentage rank value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a></td>
<td>
      Rank of current row within its partition, with gaps
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a></td>
<td>
      Number of current row within its partition
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
        In the following function descriptions,
        <em class="replaceable"><code>over_clause</code></em> represents the
        <code class="literal">OVER</code> clause, described in
        <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>. Some window functions
        permit a <em class="replaceable"><code>null_treatment</code></em> clause that
        specifies how to handle <code class="literal">NULL</code> values when
        calculating results. This clause is optional. It is part of the
        SQL standard, but the MySQL implementation permits only
        <code class="literal">RESPECT NULLS</code> (which is also the default).
        This means that <code class="literal">NULL</code> values are considered
        when calculating results. <code class="literal">IGNORE NULLS</code> is
        parsed, but produces an error.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_cume-dist"></a><p>
            <a class="link" href="functions.html#function_cume-dist"><code class="literal">CUME_DIST()</code></a>
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318758144"></a><p>
            Returns the cumulative distribution of a value within a
            group of values; that is, the percentage of partition values
            less than or equal to the value in the current row. This
            represents the number of rows preceding or peer with the
            current row in the window ordering of the window partition
            divided by the total number of rows in the window partition.
            Return values range from 0 to 1.
          </p><p>
            This function should be used with <code class="literal">ORDER
            BY</code> to sort partition rows into the desired order.
            Without <code class="literal">ORDER BY</code>, all rows are peers and
            have value
            <em class="replaceable"><code>N</code></em>/<em class="replaceable"><code>N</code></em> =
            1, where <em class="replaceable"><code>N</code></em> is the partition size.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p><p>
            The following query shows, for the set of values in the
            <code class="literal">val</code> column, the
            <code class="literal">CUME_DIST()</code> value for each row, as well
            as the percentage rank value returned by the similar
            <code class="literal">PERCENT_RANK()</code> function. For reference,
            the query also displays row numbers using
            <a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a>:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>val,</code></strong>
         <strong class="userinput"><code>ROW_NUMBER()   OVER w AS 'row_number',</code></strong>
         <strong class="userinput"><code>CUME_DIST()    OVER w AS 'cume_dist',</code></strong>
         <strong class="userinput"><code>PERCENT_RANK() OVER w AS 'percent_rank'</code></strong>
       <strong class="userinput"><code>FROM numbers</code></strong>
       <strong class="userinput"><code>WINDOW w AS (ORDER BY val);</code></strong>
+------+------------+--------------------+--------------+
| val  | row_number | cume_dist          | percent_rank |
+------+------------+--------------------+--------------+
|    1 |          1 | 0.2222222222222222 |            0 |
|    1 |          2 | 0.2222222222222222 |            0 |
|    2 |          3 | 0.3333333333333333 |         0.25 |
|    3 |          4 | 0.6666666666666666 |        0.375 |
|    3 |          5 | 0.6666666666666666 |        0.375 |
|    3 |          6 | 0.6666666666666666 |        0.375 |
|    4 |          7 | 0.8888888888888888 |         0.75 |
|    4 |          8 | 0.8888888888888888 |         0.75 |
|    5 |          9 |                  1 |            1 |
+------+------------+--------------------+--------------+
</pre></li><li class="listitem"><a name="function_dense-rank"></a><p>
            <a class="link" href="functions.html#function_dense-rank"><code class="literal">DENSE_RANK()</code></a>
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318735168"></a><p>
            Returns the rank of the current row within its partition,
            without gaps. Peers are considered ties and receive the same
            rank. This function assigns consecutive ranks to peer
            groups; the result is that groups of size greater than one
            do not produce noncontiguous rank numbers. For an example,
            see the <a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a> function
            description.
          </p><p>
            This function should be used with <code class="literal">ORDER
            BY</code> to sort partition rows into the desired order.
            Without <code class="literal">ORDER BY</code>, all rows are peers.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p></li><li class="listitem"><a name="function_first-value"></a><p>
            <a class="link" href="functions.html#function_first-value"><code class="literal">FIRST_VALUE(<em class="replaceable"><code>expr</code></em>)</code></a>
            [<em class="replaceable"><code>null_treatment</code></em>]
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318722320"></a><p>
            Returns the value of <em class="replaceable"><code>expr</code></em> from
            the first row of the window frame.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
            <em class="replaceable"><code>null_treatment</code></em> is as described in
            the section introduction.
          </p><p>
            The following query demonstrates
            <a class="link" href="functions.html#function_first-value"><code class="literal">FIRST_VALUE()</code></a>,
            <a class="link" href="functions.html#function_last-value"><code class="literal">LAST_VALUE()</code></a>, and two
            instances of <a class="link" href="functions.html#function_nth-value"><code class="literal">NTH_VALUE()</code></a>:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>time, subject, val,</code></strong>
         <strong class="userinput"><code>FIRST_VALUE(val)  OVER w AS 'first',</code></strong>
         <strong class="userinput"><code>LAST_VALUE(val)   OVER w AS 'last',</code></strong>
         <strong class="userinput"><code>NTH_VALUE(val, 2) OVER w AS 'second',</code></strong>
         <strong class="userinput"><code>NTH_VALUE(val, 4) OVER w AS 'fourth'</code></strong>
       <strong class="userinput"><code>FROM observations</code></strong>
       <strong class="userinput"><code>WINDOW w AS (PARTITION BY subject ORDER BY time</code></strong>
                    <strong class="userinput"><code>ROWS UNBOUNDED PRECEDING);</code></strong>
+----------+---------+------+-------+------+--------+--------+
| time     | subject | val  | first | last | second | fourth |
+----------+---------+------+-------+------+--------+--------+
| 07:00:00 | st113   |   10 |    10 |   10 |   NULL |   NULL |
| 07:15:00 | st113   |    9 |    10 |    9 |      9 |   NULL |
| 07:30:00 | st113   |   25 |    10 |   25 |      9 |   NULL |
| 07:45:00 | st113   |   20 |    10 |   20 |      9 |     20 |
| 07:00:00 | xh458   |    0 |     0 |    0 |   NULL |   NULL |
| 07:15:00 | xh458   |   10 |     0 |   10 |     10 |   NULL |
| 07:30:00 | xh458   |    5 |     0 |    5 |     10 |   NULL |
| 07:45:00 | xh458   |   30 |     0 |   30 |     10 |     30 |
| 08:00:00 | xh458   |   25 |     0 |   25 |     10 |     30 |
+----------+---------+------+-------+------+--------+--------+
</pre><p>
            Each function uses the rows in the current frame, which, per
            the window definition shown, extends from the first
            partition row to the current row. For the
            <a class="link" href="functions.html#function_nth-value"><code class="literal">NTH_VALUE()</code></a> calls, the
            current frame does not always include the requested row; in
            such cases, the return value is <code class="literal">NULL</code>.
          </p></li><li class="listitem"><a name="function_lag"></a><p>
            <a class="link" href="functions.html#function_lag"><code class="literal">LAG(<em class="replaceable"><code>expr</code></em> [,
            <em class="replaceable"><code>N</code></em>[,
            <em class="replaceable"><code>default</code></em>]])</code></a>
            [<em class="replaceable"><code>null_treatment</code></em>]
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318695392"></a><p>
            Returns the value of <em class="replaceable"><code>expr</code></em> from
            the row that lags (precedes) the current row by
            <em class="replaceable"><code>N</code></em> rows within its partition. If
            there is no such row, the return value is
            <em class="replaceable"><code>default</code></em>. For example, if
            <em class="replaceable"><code>N</code></em> is 3, the return value is
            <em class="replaceable"><code>default</code></em> for the first two rows.
            If <em class="replaceable"><code>N</code></em> or
            <em class="replaceable"><code>default</code></em> are missing, the defaults
            are 1 and <code class="literal">NULL</code>, respectively.
          </p><p>
            <em class="replaceable"><code>N</code></em> must be a literal nonnegative
            integer. If <em class="replaceable"><code>N</code></em> is 0,
            <em class="replaceable"><code>expr</code></em> is evaluated for the current
            row.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
            <em class="replaceable"><code>null_treatment</code></em> is as described in
            the section introduction.
          </p><p>
            <a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a> (and the similar
            <a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a> function) are often
            used to compute differences between rows. The following
            query shows a set of time-ordered observations and, for each
            one, the <a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a> and
            <a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a> values from the
            adjoining rows, as well as the differences between the
            current and adjoining rows:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>t, val,</code></strong>
         <strong class="userinput"><code>LAG(val)        OVER w AS 'lag',</code></strong>
         <strong class="userinput"><code>LEAD(val)       OVER w AS 'lead',</code></strong>
         <strong class="userinput"><code>val - LAG(val)  OVER w AS 'lag diff',</code></strong>
         <strong class="userinput"><code>val - LEAD(val) OVER w AS 'lead diff'</code></strong>
       <strong class="userinput"><code>FROM series</code></strong>
       <strong class="userinput"><code>WINDOW w AS (ORDER BY t);</code></strong>
+----------+------+------+------+----------+-----------+
| t        | val  | lag  | lead | lag diff | lead diff |
+----------+------+------+------+----------+-----------+
| 12:00:00 |  100 | NULL |  125 |     NULL |       -25 |
| 13:00:00 |  125 |  100 |  132 |       25 |        -7 |
| 14:00:00 |  132 |  125 |  145 |        7 |       -13 |
| 15:00:00 |  145 |  132 |  140 |       13 |         5 |
| 16:00:00 |  140 |  145 |  150 |       -5 |       -10 |
| 17:00:00 |  150 |  140 |  200 |       10 |       -50 |
| 18:00:00 |  200 |  150 | NULL |       50 |      NULL |
+----------+------+------+------+----------+-----------+
</pre><p>
            In the example, the <a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a> and
            <a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a> calls use the default
            <em class="replaceable"><code>N</code></em> and
            <em class="replaceable"><code>default</code></em> values of 1 and
            <code class="literal">NULL</code>, respectively.
          </p><p>
            The first row shows what happens when there is no previous
            row for <a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a>: The function
            returns the <em class="replaceable"><code>default</code></em> value (in
            this case, <code class="literal">NULL</code>). The last row shows the
            same thing when there is no next row for
            <a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a>.
          </p><p>
            <a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a> and
            <a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a> also serve to compute
            sums rather than differences. Consider this data set, which
            contains the first few numbers of the Fibonacci series:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT n FROM fib ORDER BY n;</code></strong>
+------+
| n    |
+------+
|    1 |
|    1 |
|    2 |
|    3 |
|    5 |
|    8 |
+------+
</pre><p>
            The following query shows the
            <a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a> and
            <a class="link" href="functions.html#function_lead"><code class="literal">LEAD()</code></a> values for the rows
            adjacent to the current row. It also uses those functions to
            add to the current row value the values from the preceding
            and following rows. The effect is to generate the next
            number in the Fibonacci series, and the next number after
            that:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>n,</code></strong>
         <strong class="userinput"><code>LAG(n, 1, 0)      OVER w AS 'lag',</code></strong>
         <strong class="userinput"><code>LEAD(n, 1, 0)     OVER w AS 'lead',</code></strong>
         <strong class="userinput"><code>n + LAG(n, 1, 0)  OVER w AS 'next_n',</code></strong>
         <strong class="userinput"><code>n + LEAD(n, 1, 0) OVER w AS 'next_next_n'</code></strong>
       <strong class="userinput"><code>FROM fib</code></strong>
       <strong class="userinput"><code>WINDOW w AS (ORDER BY n);</code></strong>
+------+------+------+--------+-------------+
| n    | lag  | lead | next_n | next_next_n |
+------+------+------+--------+-------------+
|    1 |    0 |    1 |      1 |           2 |
|    1 |    1 |    2 |      2 |           3 |
|    2 |    1 |    3 |      3 |           5 |
|    3 |    2 |    5 |      5 |           8 |
|    5 |    3 |    8 |      8 |          13 |
|    8 |    5 |    0 |     13 |           8 |
+------+------+------+--------+-------------+
</pre><p>
            One way to generate the initial set of Fibonacci numbers is
            to use a recursive common table expression. For an example,
            see
            <a class="xref" href="sql-statements.html#common-table-expressions-recursive-fibonacci-series" title="Fibonacci Series Generation">Fibonacci Series Generation</a>.
          </p></li><li class="listitem"><a name="function_last-value"></a><p>
            <a class="link" href="functions.html#function_last-value"><code class="literal">LAST_VALUE(<em class="replaceable"><code>expr</code></em>)</code></a>
            [<em class="replaceable"><code>null_treatment</code></em>]
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318640832"></a><p>
            Returns the value of <em class="replaceable"><code>expr</code></em> from
            the last row of the window frame.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
            <em class="replaceable"><code>null_treatment</code></em> is as described in
            the section introduction.
          </p><p>
            For an example, see the
            <a class="link" href="functions.html#function_first-value"><code class="literal">FIRST_VALUE()</code></a> function
            description.
          </p></li><li class="listitem"><a name="function_lead"></a><p>
            <a class="link" href="functions.html#function_lead"><code class="literal">LEAD(<em class="replaceable"><code>expr</code></em> [,
            <em class="replaceable"><code>N</code></em>[,
            <em class="replaceable"><code>default</code></em>]])</code></a>
            [<em class="replaceable"><code>null_treatment</code></em>]
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318627968"></a><p>
            Returns the value of <em class="replaceable"><code>expr</code></em> from
            the row that leads (follows) the current row by
            <em class="replaceable"><code>N</code></em> rows within its partition. If
            there is no such row, the return value is
            <em class="replaceable"><code>default</code></em>. For example, if
            <em class="replaceable"><code>N</code></em> is 3, the return value is
            <em class="replaceable"><code>default</code></em> for the last two rows. If
            <em class="replaceable"><code>N</code></em> or
            <em class="replaceable"><code>default</code></em> are missing, the defaults
            are 1 and <code class="literal">NULL</code>, respectively.
          </p><p>
            <em class="replaceable"><code>N</code></em> must be a literal nonnegative
            integer. If <em class="replaceable"><code>N</code></em> is 0,
            <em class="replaceable"><code>expr</code></em> is evaluated for the current
            row.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
            <em class="replaceable"><code>null_treatment</code></em> is as described in
            the section introduction.
          </p><p>
            For an example, see the <a class="link" href="functions.html#function_lag"><code class="literal">LAG()</code></a>
            function description.
          </p></li><li class="listitem"><a name="function_nth-value"></a><p>
            <a class="link" href="functions.html#function_nth-value"><code class="literal">NTH_VALUE(<em class="replaceable"><code>expr</code></em>,
            <em class="replaceable"><code>N</code></em>)</code></a>
            [<em class="replaceable"><code>from_first_last</code></em>]
            [<em class="replaceable"><code>null_treatment</code></em>]
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318609872"></a><p>
            Returns the value of <em class="replaceable"><code>expr</code></em> from
            the <em class="replaceable"><code>N</code></em>-th row of the window frame.
            If there is no such row, the return value is
            <code class="literal">NULL</code>.
          </p><p>
            <em class="replaceable"><code>N</code></em> must be a literal positive
            integer.
          </p><p>
            <em class="replaceable"><code>from_first_last</code></em> is part of the
            SQL standard, but the MySQL implementation permits only
            <code class="literal">FROM FIRST</code> (which is also the default).
            This means that calculations begin at the first row of the
            window. <code class="literal">FROM LAST</code> is parsed, but produces
            an error. To obtain the same effect as <code class="literal">FROM
            LAST</code> (begin calculations at the last row of the
            window), use <code class="literal">ORDER BY</code> to sort in reverse
            order.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
            <em class="replaceable"><code>null_treatment</code></em> is as described in
            the section introduction.
          </p><p>
            For an example, see the
            <a class="link" href="functions.html#function_first-value"><code class="literal">FIRST_VALUE()</code></a> function
            description.
          </p></li><li class="listitem"><a name="function_ntile"></a><p>
            <a class="link" href="functions.html#function_ntile"><code class="literal">NTILE(<em class="replaceable"><code>N</code></em>)</code></a>
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318592320"></a><p>
            Divides a partition into <em class="replaceable"><code>N</code></em> groups
            (buckets), assigns each row in the partition its bucket
            number, and returns the bucket number of the current row
            within its partition. For example, if
            <em class="replaceable"><code>N</code></em> is 4,
            <code class="literal">NTILE()</code> divides rows into four buckets.
            If <em class="replaceable"><code>N</code></em> is 100,
            <code class="literal">NTILE()</code> divides rows into 100 buckets.
          </p><p>
            <em class="replaceable"><code>N</code></em> must be a literal positive
            integer. Bucket number return values range from 1 to
            <em class="replaceable"><code>N</code></em>.
          </p><p>
            This function should be used with <code class="literal">ORDER
            BY</code> to sort partition rows into the desired order.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p><p>
            The following query shows, for the set of values in the
            <code class="literal">val</code> column, the percentile values
            resulting from dividing the rows into two or four groups.
            For reference, the query also displays row numbers using
            <a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a>:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>val,</code></strong>
         <strong class="userinput"><code>ROW_NUMBER() OVER w AS 'row_number',</code></strong>
         <strong class="userinput"><code>NTILE(2)     OVER w AS 'ntile2',</code></strong>
         <strong class="userinput"><code>NTILE(4)     OVER w AS 'ntile4'</code></strong>
       <strong class="userinput"><code>FROM numbers</code></strong>
       <strong class="userinput"><code>WINDOW w AS (ORDER BY val);</code></strong>
+------+------------+--------+--------+
| val  | row_number | ntile2 | ntile4 |
+------+------------+--------+--------+
|    1 |          1 |      1 |      1 |
|    1 |          2 |      1 |      1 |
|    2 |          3 |      1 |      1 |
|    3 |          4 |      1 |      2 |
|    3 |          5 |      1 |      2 |
|    3 |          6 |      2 |      3 |
|    4 |          7 |      2 |      3 |
|    4 |          8 |      2 |      4 |
|    5 |          9 |      2 |      4 |
+------+------------+--------+--------+
</pre></li><li class="listitem"><a name="function_percent-rank"></a><p>
            <a class="link" href="functions.html#function_percent-rank"><code class="literal">PERCENT_RANK()</code></a>
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318568480"></a><p>
            Returns the percentage of partition values less than the
            value in the current row, excluding the highest value.
            Return values range from 0 to 1 and represent the row
            relative rank, calculated as the result of this formula,
            where <em class="replaceable"><code>rank</code></em> is the row rank and
            <em class="replaceable"><code>rows</code></em> is the number of partition
            rows:
          </p><pre data-lang="clike" class="programlisting">(<em class="replaceable"><code>rank</code></em> - 1) / (<em class="replaceable"><code>rows</code></em> - 1)
</pre><p>
            This function should be used with <code class="literal">ORDER
            BY</code> to sort partition rows into the desired order.
            Without <code class="literal">ORDER BY</code>, all rows are peers.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p><p>
            For an example, see the
            <a class="link" href="functions.html#function_cume-dist"><code class="literal">CUME_DIST()</code></a> function
            description.
          </p></li><li class="listitem"><a name="function_rank"></a><p>
            <a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a>
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318553376"></a><p>
            Returns the rank of the current row within its partition,
            with gaps. Peers are considered ties and receive the same
            rank. This function does not assign consecutive ranks to
            peer groups if groups of size greater than one exist; the
            result is noncontiguous rank numbers.
          </p><p>
            This function should be used with <code class="literal">ORDER
            BY</code> to sort partition rows into the desired order.
            Without <code class="literal">ORDER BY</code>, all rows are peers.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
          </p><p>
            The following query shows the difference between
            <a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a>, which produces ranks
            with gaps, and <a class="link" href="functions.html#function_dense-rank"><code class="literal">DENSE_RANK()</code></a>,
            which produces ranks without gaps. The query shows rank
            values for each member of a set of values in the
            <code class="literal">val</code> column, which contains some
            duplicates. <a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a> assigns
            peers (the duplicates) the same rank value, and the next
            greater value has a rank higher by the number of peers minus
            one. <a class="link" href="functions.html#function_dense-rank"><code class="literal">DENSE_RANK()</code></a> also
            assigns peers the same rank value, but the next higher value
            has a rank one greater. For reference, the query also
            displays row numbers using
            <a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a>:
          </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>val,</code></strong>
         <strong class="userinput"><code>ROW_NUMBER() OVER w AS 'row_number',</code></strong>
         <strong class="userinput"><code>RANK()       OVER w AS 'rank',</code></strong>
         <strong class="userinput"><code>DENSE_RANK() OVER w AS 'dense_rank'</code></strong>
       <strong class="userinput"><code>FROM numbers</code></strong>
       <strong class="userinput"><code>WINDOW w AS (ORDER BY val);</code></strong>
+------+------------+------+------------+
| val  | row_number | rank | dense_rank |
+------+------------+------+------------+
|    1 |          1 |    1 |          1 |
|    1 |          2 |    1 |          1 |
|    2 |          3 |    3 |          2 |
|    3 |          4 |    4 |          3 |
|    3 |          5 |    4 |          3 |
|    3 |          6 |    4 |          3 |
|    4 |          7 |    7 |          4 |
|    4 |          8 |    7 |          4 |
|    5 |          9 |    9 |          5 |
+------+------------+------+------------+
</pre></li><li class="listitem"><a name="function_row-number"></a><p>
            <a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a>
            <em class="replaceable"><code>over_clause</code></em>
          </p><a class="indexterm" name="idm46444318527504"></a><p>
            Returns the number of the current row within its partition.
            Rows numbers range from 1 to the number of partition rows.
          </p><p>
            <code class="literal">ORDER BY</code> affects the order in which rows
            are numbered. Without <code class="literal">ORDER BY</code>, row
            numbering is nondeterministic.
          </p><p>
            <a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a> assigns peers
            different row numbers. To assign peers the same value, use
            <a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a> or
            <a class="link" href="functions.html#function_dense-rank"><code class="literal">DENSE_RANK()</code></a>. For an example,
            see the <a class="link" href="functions.html#function_rank"><code class="literal">RANK()</code></a> function
            description.
          </p><p>
            <em class="replaceable"><code>over_clause</code></em> is as described in
            <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="window-functions-usage"></a>12.21.2 Window Function Concepts and Syntax</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444318514928"></a><p>
        This section describes how to use window functions. Examples use
        the same sales information data set as found in the discussion
        of the <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> function in
        <a class="xref" href="functions.html#group-by-modifiers" title="12.20.2 GROUP BY Modifiers">Section 12.20.2, “GROUP BY Modifiers”</a>:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM sales ORDER BY country, year, product;</code></strong>
+------+---------+------------+--------+
| year | country | product    | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer   |   1500 |
| 2000 | Finland | Phone      |    100 |
| 2001 | Finland | Phone      |     10 |
| 2000 | India   | Calculator |     75 |
| 2000 | India   | Calculator |     75 |
| 2000 | India   | Computer   |   1200 |
| 2000 | USA     | Calculator |     75 |
| 2000 | USA     | Computer   |   1500 |
| 2001 | USA     | Calculator |     50 |
| 2001 | USA     | Computer   |   1500 |
| 2001 | USA     | Computer   |   1200 |
| 2001 | USA     | TV         |    150 |
| 2001 | USA     | TV         |    100 |
+------+---------+------------+--------+
</pre><a class="indexterm" name="idm46444318509232"></a><a class="indexterm" name="idm46444318507744"></a><p>
        A window function performs an aggregate-like operation on a set
        of query rows. However, whereas an aggregate operation groups
        query rows into a single result row, a window function produces
        a result for each query row:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            The row for which function evaluation occurs is called the
            current row.
          </p></li><li class="listitem"><p>
            The query rows related to the current row over which
            function evaluation occurs comprise the window for the
            current row.
</p></li></ul>
</div>
<p>
        For example, using the sales information table, these two
        queries perform aggregate operations that produce a single
        global sum for all rows taken as a group, and sums grouped per
        country:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SUM(profit) AS total_profit</code></strong>
       <strong class="userinput"><code>FROM sales;</code></strong>
+--------------+
| total_profit |
+--------------+
|         7535 |
+--------------+
mysql&gt; <strong class="userinput"><code>SELECT country, SUM(profit) AS country_profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>GROUP BY country</code></strong>
       <strong class="userinput"><code>ORDER BY country;</code></strong>
+---------+----------------+
| country | country_profit |
+---------+----------------+
| Finland |           1610 |
| India   |           1350 |
| USA     |           4575 |
+---------+----------------+
</pre><p>
        By contrast, window operations do not collapse groups of query
        rows to a single output row. Instead, they produce a result for
        each row. Like the preceding queries, the following query uses
        <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a>, but this time as a window
        function:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>year, country, product, profit,</code></strong>
         <strong class="userinput"><code>SUM(profit) OVER() AS total_profit,</code></strong>
         <strong class="userinput"><code>SUM(profit) OVER(PARTITION BY country) AS country_profit</code></strong>
       <strong class="userinput"><code>FROM sales</code></strong>
       <strong class="userinput"><code>ORDER BY country, year, product, profit;</code></strong>
+------+---------+------------+--------+--------------+----------------+
| year | country | product    | profit | total_profit | country_profit |
+------+---------+------------+--------+--------------+----------------+
| 2000 | Finland | Computer   |   1500 |         7535 |           1610 |
| 2000 | Finland | Phone      |    100 |         7535 |           1610 |
| 2001 | Finland | Phone      |     10 |         7535 |           1610 |
| 2000 | India   | Calculator |     75 |         7535 |           1350 |
| 2000 | India   | Calculator |     75 |         7535 |           1350 |
| 2000 | India   | Computer   |   1200 |         7535 |           1350 |
| 2000 | USA     | Calculator |     75 |         7535 |           4575 |
| 2000 | USA     | Computer   |   1500 |         7535 |           4575 |
| 2001 | USA     | Calculator |     50 |         7535 |           4575 |
| 2001 | USA     | Computer   |   1200 |         7535 |           4575 |
| 2001 | USA     | Computer   |   1500 |         7535 |           4575 |
| 2001 | USA     | TV         |    100 |         7535 |           4575 |
| 2001 | USA     | TV         |    150 |         7535 |           4575 |
+------+---------+------------+--------+--------------+----------------+
</pre><a class="indexterm" name="idm46444318488880"></a><p>
        Each window operation in the query is signified by inclusion of
        an <code class="literal">OVER</code> clause that specifies how to
        partition query rows into groups for processing by the window
        function:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            The first <code class="literal">OVER</code> clause is empty, which
            treats the entire set of query rows as a single partition.
            The window function thus produces a global sum, but does so
            for each row.
          </p></li><li class="listitem"><p>
            The second <code class="literal">OVER</code> clause partitions rows by
            country, producing a sum per partition (per country). The
            function produces this sum for each partition row.
</p></li></ul>
</div>
<p>
        Window functions are permitted only in the select list and
        <code class="literal">ORDER BY</code> clause. Query result rows are
        determined from the <code class="literal">FROM</code> clause, after
        <code class="literal">WHERE</code>, <code class="literal">GROUP BY</code>, and
        <code class="literal">HAVING</code> processing, and windowing execution
        occurs before <code class="literal">ORDER BY</code>,
        <code class="literal">LIMIT</code>, and <code class="literal">SELECT
        DISTINCT</code>.
      </p><p>
        The <code class="literal">OVER</code> clause is permitted for many
        aggregate functions, which therefore can be used as window or
        nonwindow functions, depending on whether the
        <code class="literal">OVER</code> clause is present or absent:
      </p><pre data-lang="sql" class="programlisting">AVG()
BIT_AND()
BIT_OR()
BIT_XOR()
COUNT()
JSON_ARRAYAGG()
JSON_OBJECTAGG()
MAX()
MIN()
STDDEV_POP(), STDDEV(), STD()
STDDEV_SAMP()
SUM()
VAR_POP(), VARIANCE()
VAR_SAMP()</pre><p>
        For details about each aggregate function, see
        <a class="xref" href="functions.html#group-by-functions" title="12.20.1 Aggregate (GROUP BY) Function Descriptions">Section 12.20.1, “Aggregate (GROUP BY) Function Descriptions”</a>.
      </p><p>
        MySQL also supports nonaggregate functions that are used only as
        window functions. For these, the <code class="literal">OVER</code> clause
        is mandatory:
      </p><pre data-lang="sql" class="programlisting">CUME_DIST()
DENSE_RANK()
FIRST_VALUE()
LAG()
LAST_VALUE()
LEAD()
NTH_VALUE()
NTILE()
PERCENT_RANK()
RANK()
ROW_NUMBER()</pre><p>
        For details about each nonaggregate function, see
        <a class="xref" href="functions.html#window-function-descriptions" title="12.21.1 Window Function Descriptions">Section 12.21.1, “Window Function Descriptions”</a>.
      </p><p>
        As an example of one of those nonaggregate window functions,
        this query uses <a class="link" href="functions.html#function_row-number"><code class="literal">ROW_NUMBER()</code></a>,
        which produces the row number of each row within its partition.
        In this case, rows are numbered per country. By default,
        partition rows are unordered and row numbering is
        nondeterministic. To sort partition rows, include an
        <code class="literal">ORDER BY</code> clause within the window definition.
        The query uses unordered and ordered partitions (the
        <code class="literal">row_num1</code> and <code class="literal">row_num2</code>
        columns) to illustrate the difference between omitting and
        including <code class="literal">ORDER BY</code>:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>year, country, product, profit,</code></strong>
         <strong class="userinput"><code>ROW_NUMBER() OVER(PARTITION BY country) AS row_num1,</code></strong>
         <strong class="userinput"><code>ROW_NUMBER() OVER(PARTITION BY country ORDER BY year, product) AS row_num2</code></strong>
       <strong class="userinput"><code>FROM sales;</code></strong>
+------+---------+------------+--------+----------+----------+
| year | country | product    | profit | row_num1 | row_num2 |
+------+---------+------------+--------+----------+----------+
| 2000 | Finland | Computer   |   1500 |        2 |        1 |
| 2000 | Finland | Phone      |    100 |        1 |        2 |
| 2001 | Finland | Phone      |     10 |        3 |        3 |
| 2000 | India   | Calculator |     75 |        2 |        1 |
| 2000 | India   | Calculator |     75 |        3 |        2 |
| 2000 | India   | Computer   |   1200 |        1 |        3 |
| 2000 | USA     | Calculator |     75 |        5 |        1 |
| 2000 | USA     | Computer   |   1500 |        4 |        2 |
| 2001 | USA     | Calculator |     50 |        2 |        3 |
| 2001 | USA     | Computer   |   1500 |        3 |        4 |
| 2001 | USA     | Computer   |   1200 |        7 |        5 |
| 2001 | USA     | TV         |    150 |        1 |        6 |
| 2001 | USA     | TV         |    100 |        6 |        7 |
+------+---------+------------+--------+----------+----------+
</pre><p>
        As mentioned previously, to use a window function (or treat an
        aggregate function as a window function), include an
        <code class="literal">OVER</code> clause following the function call. The
        <code class="literal">OVER</code> clause has two forms:
      </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>over_clause</code></em>:
    {OVER (<em class="replaceable"><code>window_spec</code></em>) | OVER <em class="replaceable"><code>window_name</code></em>}
</pre><p>
        Both forms define how the window function should process query
        rows. They differ in whether the window is defined directly in
        the <code class="literal">OVER</code> clause, or supplied by a reference
        to a named window defined elsewhere in the query:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            In the first case, the window specification appears directly
            in the <code class="literal">OVER</code> clause, between the
            parentheses.
          </p></li><li class="listitem"><p>
            In the second case, <em class="replaceable"><code>window_name</code></em>
            is the name for a window specification defined by a
            <code class="literal">WINDOW</code> clause elsewhere in the query. For
            details, see
            <a class="xref" href="functions.html#window-functions-named-windows" title="12.21.4 Named Windows">Section 12.21.4, “Named Windows”</a>.
</p></li></ul>
</div>
<p>
        For <code class="literal">OVER
        (<em class="replaceable"><code>window_spec</code></em>)</code> syntax, the
        window specification has several parts, all optional:
      </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>window_spec</code></em>:
    [<em class="replaceable"><code>window_name</code></em>] [<em class="replaceable"><code>partition_clause</code></em>] [<em class="replaceable"><code>order_clause</code></em>] [<em class="replaceable"><code>frame_clause</code></em>]
</pre><p>
        If <code class="literal">OVER()</code> is empty, the window consists of
        all query rows and the window function computes a result using
        all rows. Otherwise, the clauses present within the parentheses
        determine which query rows are used to compute the function
        result and how they are partitioned and ordered:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <em class="replaceable"><code>window_name</code></em>: The name of a window
            defined by a <code class="literal">WINDOW</code> clause elsewhere in
            the query. If <em class="replaceable"><code>window_name</code></em> appears
            by itself within the <code class="literal">OVER</code> clause, it
            completely defines the window. If partitioning, ordering, or
            framing clauses are also given, they modify interpretation
            of the named window. For details, see
            <a class="xref" href="functions.html#window-functions-named-windows" title="12.21.4 Named Windows">Section 12.21.4, “Named Windows”</a>.
          </p></li><li class="listitem"><p>
            <em class="replaceable"><code>partition_clause</code></em>: A
            <code class="literal">PARTITION BY</code> clause indicates how to
            divide the query rows into groups. The window function
            result for a given row is based on the rows of the partition
            that contains the row. If <code class="literal">PARTITION BY</code> is
            omitted, there is a single partition consisting of all query
            rows.
</p><a class="indexterm" name="idm46444318433936"></a><a class="indexterm" name="idm46444318432448"></a>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
              Partitioning for window functions differs from table
              partitioning. For information about table partitioning,
              see <a class="xref" href="partitioning.html" title="Chapter 23 Partitioning">Chapter 23, <i>Partitioning</i></a>.
</p>
</div>
<p>
            <em class="replaceable"><code>partition_clause</code></em> has this syntax:
          </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>partition_clause</code></em>:
    PARTITION BY <em class="replaceable"><code>expr</code></em> [, <em class="replaceable"><code>expr</code></em>] ...
</pre><p>
            Standard SQL requires <code class="literal">PARTITION BY</code> to be
            followed by column names only. A MySQL extension is to
            permit expressions, not just column names. For example, if a
            table contains a <a class="link" href="data-types.html#datetime" title="11.2.2 The DATE, DATETIME, and TIMESTAMP Types"><code class="literal">TIMESTAMP</code></a>
            column named <code class="literal">ts</code>, standard SQL permits
            <code class="literal">PARTITION BY ts</code> but not
            <code class="literal">PARTITION BY HOUR(ts)</code>, whereas MySQL
            permits both.
          </p></li><li class="listitem"><p>
            <em class="replaceable"><code>order_clause</code></em>: An <code class="literal">ORDER
            BY</code> clause indicates how to sort rows in each
            partition. Partition rows that are equal according to the
            <code class="literal">ORDER BY</code> clause are considered peers. If
            <code class="literal">ORDER BY</code> is omitted, partition rows are
            unordered, with no processing order implied, and all
            partition rows are peers.
          </p><a class="indexterm" name="idm46444318417872"></a><a class="indexterm" name="idm46444318416384"></a><p>
            <em class="replaceable"><code>order_clause</code></em> has this syntax:
          </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>order_clause</code></em>:
    ORDER BY <em class="replaceable"><code>expr</code></em> [ASC|DESC] [, <em class="replaceable"><code>expr</code></em> [ASC|DESC]] ...
</pre><p>
            Each <code class="literal">ORDER BY</code> expression optionally can
            be followed by <code class="literal">ASC</code> or
            <code class="literal">DESC</code> to indicate sort direction. The
            default is <code class="literal">ASC</code> if no direction is
            specified. <code class="literal">NULL</code> values sort first for
            ascending sorts, last for descending sorts.
          </p><p>
            An <code class="literal">ORDER BY</code> in a window definition
            applies within individual partitions. To sort the result set
            as a whole, include an <code class="literal">ORDER BY</code> at the
            query top level.
          </p></li><li class="listitem"><p>
            <em class="replaceable"><code>frame_clause</code></em>: A frame is a subset
            of the current partition and the frame clause specifies how
            to define the subset. The frame clause has many subclauses
            of its own. For details, see
            <a class="xref" href="functions.html#window-functions-frames" title="12.21.3 Window Function Frame Specification">Section 12.21.3, “Window Function Frame Specification”</a>.
</p><a class="indexterm" name="idm46444318403520"></a></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="window-functions-frames"></a>12.21.3 Window Function Frame Specification</h3>

</div>

</div>

</div>
<a class="indexterm" name="idm46444318400496"></a><p>
        The definition of a window used with a window function can
        include a frame clause. A frame is a subset of the current
        partition and the frame clause specifies how to define the
        subset.
      </p><p>
        Frames are determined with respect to the current row, which
        enables a frame to move within a partition depending on the
        location of the current row within its partition. Examples:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            By defining a frame to be all rows from the partition start
            to the current row, you can compute running totals for each
            row.
          </p></li><li class="listitem"><p>
            By defining a frame as extending
            <em class="replaceable"><code>N</code></em> rows on either side of the
            current row, you can compute rolling averages.
</p></li></ul>
</div>
<p>
        The following query demonstrates the use of moving frames to
        compute running totals within each group of time-ordered
        <code class="literal">level</code> values, as well as rolling averages
        computed from the current row and the rows that immediately
        precede and follow it:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>time, subject, val,</code></strong>
         <strong class="userinput"><code>SUM(val) OVER (PARTITION BY subject ORDER BY time</code></strong>
                        <strong class="userinput"><code>ROWS UNBOUNDED PRECEDING)</code></strong>
           <strong class="userinput"><code>AS running_total,</code></strong>
         <strong class="userinput"><code>AVG(val) OVER (PARTITION BY subject ORDER BY time</code></strong>
                        <strong class="userinput"><code>ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)</code></strong>
           <strong class="userinput"><code>AS running_average</code></strong>
       <strong class="userinput"><code>FROM observations;</code></strong>
+----------+---------+------+---------------+-----------------+
| time     | subject | val  | running_total | running_average |
+----------+---------+------+---------------+-----------------+
| 07:00:00 | st113   |   10 |            10 |          9.5000 |
| 07:15:00 | st113   |    9 |            19 |         14.6667 |
| 07:30:00 | st113   |   25 |            44 |         18.0000 |
| 07:45:00 | st113   |   20 |            64 |         22.5000 |
| 07:00:00 | xh458   |    0 |             0 |          5.0000 |
| 07:15:00 | xh458   |   10 |            10 |          5.0000 |
| 07:30:00 | xh458   |    5 |            15 |         15.0000 |
| 07:45:00 | xh458   |   30 |            45 |         20.0000 |
| 08:00:00 | xh458   |   25 |            70 |         27.5000 |
+----------+---------+------+---------------+-----------------+
</pre><p>
        For the <code class="literal">running_average</code> column, there is no
        frame row preceding the first one or following the last. In
        these cases, <a class="link" href="functions.html#function_avg"><code class="literal">AVG()</code></a> computes the
        average of the rows that are available.
      </p><p>
        Aggregate functions used as window functions operate on rows in
        the current row frame, as do these nonaggregate window
        functions:
      </p><pre data-lang="sql" class="programlisting">FIRST_VALUE()
LAST_VALUE()
NTH_VALUE()</pre><p>
        Standard SQL specifies that window functions that operate on the
        entire partition should have no frame clause. MySQL permits a
        frame clause for such functions but ignores it. These functions
        use the entire partition even if a frame is specified:
      </p><pre data-lang="sql" class="programlisting">CUME_DIST()
DENSE_RANK()
LAG()
LEAD()
NTILE()
PERCENT_RANK()
RANK()
ROW_NUMBER()</pre><p>
        The frame clause, if given, has this syntax:
      </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>frame_clause</code></em>:
    <em class="replaceable"><code>frame_units</code></em> <em class="replaceable"><code>frame_extent</code></em>

<em class="replaceable"><code>frame_units</code></em>:
    {ROWS | RANGE}
</pre><p>
        In the absence of a frame clause, the default frame depends on
        whether an <code class="literal">ORDER BY</code> clause is present, as
        described later in this section.
      </p><p>
        The <em class="replaceable"><code>frame_units</code></em> value indicates the
        type of relationship between the current row and frame rows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <code class="literal">ROWS</code>: The frame is defined by beginning
            and ending row positions. Offsets are differences in row
            numbers from the current row number.
          </p></li><li class="listitem"><p>
            <code class="literal">RANGE</code>: The frame is defined by rows
            within a value range. Offsets are differences in row values
            from the current row value.
</p></li></ul>
</div>
<p>
        The <em class="replaceable"><code>frame_extent</code></em> value indicates the
        start and end points of the frame. You can specify just the
        start of the frame (in which case the current row is implicitly
        the end) or use <code class="literal">BETWEEN</code> to specify both frame
        endpoints:
      </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>frame_extent</code></em>:
    {<em class="replaceable"><code>frame_start</code></em> | <em class="replaceable"><code>frame_between</code></em>}

<em class="replaceable"><code>frame_between</code></em>:
    BETWEEN <em class="replaceable"><code>frame_start</code></em> AND <em class="replaceable"><code>frame_end</code></em>

<em class="replaceable"><code>frame_start</code></em>, <em class="replaceable"><code>frame_end</code></em>: {
    CURRENT ROW
  | UNBOUNDED PRECEDING
  | UNBOUNDED FOLLOWING
  | <em class="replaceable"><code>expr</code></em> PRECEDING
  | <em class="replaceable"><code>expr</code></em> FOLLOWING
}
</pre><p>
        With <code class="literal">BETWEEN</code> syntax,
        <em class="replaceable"><code>frame_start</code></em> must not occur later than
        <em class="replaceable"><code>frame_end</code></em>.
      </p><p>
        The permitted <em class="replaceable"><code>frame_start</code></em> and
        <em class="replaceable"><code>frame_end</code></em> values have these meanings:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <code class="literal">CURRENT ROW</code>: For <code class="literal">ROWS</code>,
            the bound is the current row. For <code class="literal">RANGE</code>,
            the bound is the peers of the current row.
          </p></li><li class="listitem"><p>
            <code class="literal">UNBOUNDED PRECEDING</code>: The bound is the
            first partition row.
          </p></li><li class="listitem"><p>
            <code class="literal">UNBOUNDED FOLLOWING</code>: The bound is the
            last partition row.
          </p></li><li class="listitem"><p>
            <code class="literal"><em class="replaceable"><code>expr</code></em>
            PRECEDING</code>: For <code class="literal">ROWS</code>, the bound
            is <em class="replaceable"><code>expr</code></em> rows before the current
            row. For <code class="literal">RANGE</code>, the bound is the rows
            with values equal to the current row value minus
            <em class="replaceable"><code>expr</code></em>; if the current row value is
            <code class="literal">NULL</code>, the bound is the peers of the row.
          </p><p>
            For <code class="literal"><em class="replaceable"><code>expr</code></em>
            PRECEDING</code> (and
            <code class="literal"><em class="replaceable"><code>expr</code></em>
            FOLLOWING</code>), <em class="replaceable"><code>expr</code></em> can be
            a <code class="literal">?</code> parameter marker (for use in a
            prepared statement), a nonnegative numeric literal, or a
            temporal interval of the form <code class="literal">INTERVAL
            <em class="replaceable"><code>val</code></em>
            <em class="replaceable"><code>unit</code></em></code>. For
            <code class="literal">INTERVAL</code> expressions,
            <em class="replaceable"><code>val</code></em> specifies nonnegative
            interval value, and <em class="replaceable"><code>unit</code></em> is a
            keyword indicating the units in which the value should be
            interpreted. (For details about the permitted
            <em class="replaceable"><code>units</code></em> specifiers, see the
            description of the <a class="link" href="functions.html#function_date-add"><code class="literal">DATE_ADD()</code></a>
            function in <a class="xref" href="functions.html#date-and-time-functions" title="12.6 Date and Time Functions">Section 12.6, “Date and Time Functions”</a>.)
          </p><p>
            <code class="literal">RANGE</code> on a numeric or temporal
            <em class="replaceable"><code>expr</code></em> requires <code class="literal">ORDER
            BY</code> on a numeric or temporal expression,
            respectively.
          </p><p>
            Examples of valid <code class="literal"><em class="replaceable"><code>expr</code></em>
            PRECEDING</code> and
            <code class="literal"><em class="replaceable"><code>expr</code></em> FOLLOWING</code>
            indicators:
          </p><pre data-lang="sql" class="programlisting">10 PRECEDING
INTERVAL 5 DAY PRECEDING
5 FOLLOWING
INTERVAL '2:30' MINUTE_SECOND FOLLOWING</pre></li><li class="listitem"><p>
            <code class="literal"><em class="replaceable"><code>expr</code></em>
            FOLLOWING</code>: For <code class="literal">ROWS</code>, the bound
            is <em class="replaceable"><code>expr</code></em> rows after the current
            row. For <code class="literal">RANGE</code>, the bound is the rows
            with values equal to the current row value plus
            <em class="replaceable"><code>expr</code></em>; if the current row value is
            <code class="literal">NULL</code>, the bound is the peers of the row.
          </p><p>
            For permitted values of <em class="replaceable"><code>expr</code></em>, see
            the description of <code class="literal"><em class="replaceable"><code>expr</code></em>
            PRECEDING</code>.
</p></li></ul>
</div>
<p>
        The following query demonstrates
        <a class="link" href="functions.html#function_first-value"><code class="literal">FIRST_VALUE()</code></a>,
        <a class="link" href="functions.html#function_last-value"><code class="literal">LAST_VALUE()</code></a>, and two instances
        of <a class="link" href="functions.html#function_nth-value"><code class="literal">NTH_VALUE()</code></a>:
      </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>time, subject, val,</code></strong>
         <strong class="userinput"><code>FIRST_VALUE(val)  OVER w AS 'first',</code></strong>
         <strong class="userinput"><code>LAST_VALUE(val)   OVER w AS 'last',</code></strong>
         <strong class="userinput"><code>NTH_VALUE(val, 2) OVER w AS 'second',</code></strong>
         <strong class="userinput"><code>NTH_VALUE(val, 4) OVER w AS 'fourth'</code></strong>
       <strong class="userinput"><code>FROM observations</code></strong>
       <strong class="userinput"><code>WINDOW w AS (PARTITION BY subject ORDER BY time</code></strong>
                    <strong class="userinput"><code>ROWS UNBOUNDED PRECEDING);</code></strong>
+----------+---------+------+-------+------+--------+--------+
| time     | subject | val  | first | last | second | fourth |
+----------+---------+------+-------+------+--------+--------+
| 07:00:00 | st113   |   10 |    10 |   10 |   NULL |   NULL |
| 07:15:00 | st113   |    9 |    10 |    9 |      9 |   NULL |
| 07:30:00 | st113   |   25 |    10 |   25 |      9 |   NULL |
| 07:45:00 | st113   |   20 |    10 |   20 |      9 |     20 |
| 07:00:00 | xh458   |    0 |     0 |    0 |   NULL |   NULL |
| 07:15:00 | xh458   |   10 |     0 |   10 |     10 |   NULL |
| 07:30:00 | xh458   |    5 |     0 |    5 |     10 |   NULL |
| 07:45:00 | xh458   |   30 |     0 |   30 |     10 |     30 |
| 08:00:00 | xh458   |   25 |     0 |   25 |     10 |     30 |
+----------+---------+------+-------+------+--------+--------+
</pre><p>
        Each function uses the rows in the current frame, which, per the
        window definition shown, extends from the first partition row to
        the current row. For the
        <a class="link" href="functions.html#function_nth-value"><code class="literal">NTH_VALUE()</code></a> calls, the current
        frame does not always include the requested row; in such cases,
        the return value is <code class="literal">NULL</code>.
      </p><p>
        In the absence of a frame clause, the default frame depends on
        whether an <code class="literal">ORDER BY</code> clause is present:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            With <code class="literal">ORDER BY</code>: The default frame includes
            rows from the partition start through the current row,
            including all peers of the current row (rows equal to the
            current row according to the <code class="literal">ORDER BY</code>
            clause). The default is equivalent to this frame
            specification:
          </p><pre data-lang="sql" class="programlisting">RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW</pre></li><li class="listitem"><p>
            Without <code class="literal">ORDER BY</code>: The default frame
            includes all partition rows (because, without <code class="literal">ORDER
            BY</code>, all partition rows are peers). The default is
            equivalent to this frame specification:
</p><pre data-lang="sql" class="programlisting">RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING</pre></li></ul>
</div>
<p>
        Because the default frame differs depending on presence or
        absence of <code class="literal">ORDER BY</code>, adding <code class="literal">ORDER
        BY</code> to a query to get deterministic results may change
        the results. (For example, the values produced by
        <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a> might change.) To obtain
        the same results but ordered per <code class="literal">ORDER BY</code>,
        provide an explicit frame specification to be used regardless of
        whether <code class="literal">ORDER BY</code> is present.
      </p><p>
        The meaning of a frame specification can be nonobvious when the
        current row value is <code class="literal">NULL</code>. Assuming that to
        be the case, these examples illustrate how various frame
        specifications apply:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <code class="literal">ORDER BY X ASC RANGE BETWEEN 10 FOLLOWING AND 15
            FOLLOWING</code>
          </p><p>
            The frame starts at <code class="literal">NULL</code> and stops at
            <code class="literal">NULL</code>, thus includes only rows with value
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            <code class="literal">ORDER BY X ASC RANGE BETWEEN 10 FOLLOWING AND
            UNBOUNDED FOLLOWING</code>
          </p><p>
            The frame starts at <code class="literal">NULL</code> and stops at the
            end of the partition. Because an <code class="literal">ASC</code> sort
            puts <code class="literal">NULL</code> values first, the frame is the
            entire partition.
          </p></li><li class="listitem"><p>
            <code class="literal">ORDER BY X DESC RANGE BETWEEN 10 FOLLOWING AND
            UNBOUNDED FOLLOWING</code>
          </p><p>
            The frame starts at <code class="literal">NULL</code> and stops at the
            end of the partition. Because a <code class="literal">DESC</code> sort
            puts <code class="literal">NULL</code> values last, the frame is only
            the <code class="literal">NULL</code> values.
          </p></li><li class="listitem"><p>
            <code class="literal">ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND
            UNBOUNDED FOLLOWING</code>
          </p><p>
            The frame starts at <code class="literal">NULL</code> and stops at the
            end of the partition. Because an <code class="literal">ASC</code> sort
            puts <code class="literal">NULL</code> values first, the frame is the
            entire partition.
          </p></li><li class="listitem"><p>
            <code class="literal">ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 10
            FOLLOWING</code>
          </p><p>
            The frame starts at <code class="literal">NULL</code> and stops at
            <code class="literal">NULL</code>, thus includes only rows with value
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            <code class="literal">ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 1
            PRECEDING</code>
          </p><p>
            The frame starts at <code class="literal">NULL</code> and stops at
            <code class="literal">NULL</code>, thus includes only rows with value
            <code class="literal">NULL</code>.
          </p></li><li class="listitem"><p>
            <code class="literal">ORDER BY X ASC RANGE BETWEEN UNBOUNDED PRECEDING
            AND 10 FOLLOWING</code>
          </p><p>
            The frame starts at the beginning of the partition and stops
            at rows with value <code class="literal">NULL</code>. Because an
            <code class="literal">ASC</code> sort puts <code class="literal">NULL</code>
            values first, the frame is only the <code class="literal">NULL</code>
            values.
</p></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="window-functions-named-windows"></a>12.21.4 Named Windows</h3>

</div>

</div>

</div>
<p>
        Windows can be defined and given names by which to refer to them
        in <code class="literal">OVER</code> clauses. To do this, use a
        <code class="literal">WINDOW</code> clause. If present in a query, the
        <code class="literal">WINDOW</code> clause falls between the positions of
        the <code class="literal">HAVING</code> and <code class="literal">ORDER BY</code>
        clauses, and has this syntax:
      </p><pre data-lang="sql" class="programlisting">WINDOW <em class="replaceable"><code>window_name</code></em> AS (<em class="replaceable"><code>window_spec</code></em>)
    [, <em class="replaceable"><code>window_name</code></em> AS (<em class="replaceable"><code>window_spec</code></em>)] ...
</pre><p>
        For each window definition,
        <em class="replaceable"><code>window_name</code></em> is the window name, and
        <em class="replaceable"><code>window_spec</code></em> is the same type of
        window specification as given between the parentheses of an
        <code class="literal">OVER</code> clause, as described in
        <a class="xref" href="functions.html#window-functions-usage" title="12.21.2 Window Function Concepts and Syntax">Section 12.21.2, “Window Function Concepts and Syntax”</a>:
      </p><pre data-lang="sql" class="programlisting"><em class="replaceable"><code>window_spec</code></em>:
    [<em class="replaceable"><code>window_name</code></em>] [<em class="replaceable"><code>partition_clause</code></em>] [<em class="replaceable"><code>order_clause</code></em>] [<em class="replaceable"><code>frame_clause</code></em>]
</pre><p>
        A <code class="literal">WINDOW</code> clause is useful for queries in
        which multiple <code class="literal">OVER</code> clauses would otherwise
        define the same window. Instead, you can define the window once,
        give it a name, and refer to the name in the
        <code class="literal">OVER</code> clauses. Consider this query, which
        defines the same window multiple times:
      </p><pre data-lang="sql" class="programlisting">SELECT
  val,
  ROW_NUMBER() OVER (ORDER BY val) AS 'row_number',
  RANK()       OVER (ORDER BY val) AS 'rank',
  DENSE_RANK() OVER (ORDER BY val) AS 'dense_rank'
FROM numbers;</pre><p>
        The query can be written more simply by using
        <code class="literal">WINDOW</code> to define the window once and
        referring to the window by name in the <code class="literal">OVER</code>
        clauses:
      </p><pre data-lang="sql" class="programlisting">SELECT
  val,
  ROW_NUMBER() OVER w AS 'row_number',
  RANK()       OVER w AS 'rank',
  DENSE_RANK() OVER w AS 'dense_rank'
FROM numbers
WINDOW w AS (ORDER BY val);</pre><p>
        A named window also makes it easier to experiment with the
        window definition to see the effect on query results. You need
        only modify the window definition in the
        <code class="literal">WINDOW</code> clause, rather than multiple
        <code class="literal">OVER</code> clause definitions.
      </p><p>
        If an <code class="literal">OVER</code> clause uses <code class="literal">OVER
        (<em class="replaceable"><code>window_name</code></em> ...)</code> rather
        than <code class="literal">OVER
        <em class="replaceable"><code>window_name</code></em></code>, the named
        window can be modified by the addition of other clauses. For
        example, this query defines a window that includes partitioning,
        and uses <code class="literal">ORDER BY</code> in the
        <code class="literal">OVER</code> clauses to modify the window in
        different ways:
      </p><pre data-lang="sql" class="programlisting">SELECT
  DISTINCT year, country,
  FIRST_VALUE(year) OVER (w ORDER BY year ASC) AS first,
  FIRST_VALUE(year) OVER (w ORDER BY year DESC) AS last
FROM sales
WINDOW w AS (PARTITION BY country);</pre><p>
        An <code class="literal">OVER</code> clause can only add properties to a
        named window, not modify them. If the named window definition
        includes a partitioning, ordering, or framing property, the
        <code class="literal">OVER</code> clause that refers to the window name
        cannot also include the same kind of property or an error
        occurs:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            This construct is permitted because the window definition
            and the referring <code class="literal">OVER</code> clause do not
            contain the same kind of properties:
          </p><pre data-lang="sql" class="programlisting">OVER (w ORDER BY country)
... WINDOW w AS (PARTITION BY country)</pre></li><li class="listitem"><p>
            This construct is not permitted because the
            <code class="literal">OVER</code> clause specifies <code class="literal">PARTITION
            BY</code> for a named window that already has
            <code class="literal">PARTITION BY</code>:
          </p><pre data-lang="sql" class="programlisting">OVER (w PARTITION BY year)
... WINDOW w AS (PARTITION BY country)</pre></li></ul>
</div>
<p>
        The definition of a named window can itself begin with a
        <em class="replaceable"><code>window_name</code></em>. In such cases, forward
        and backward references are permitted, but not cycles:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            This is permitted; it contains forward and backward
            references but no cycles:
          </p><pre data-lang="sql" class="programlisting">WINDOW w1 AS (w2), w2 AS (), w3 AS (w1)</pre></li><li class="listitem"><p>
            This is not permitted because it contains a cycle:
</p><pre data-lang="sql" class="programlisting">WINDOW w1 AS (w2), w2 AS (w3), w3 AS (w1)</pre></li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="window-function-restrictions"></a>12.21.5 Window Function Restrictions</h3>

</div>

</div>

</div>
<p>
        The SQL standard imposes a constraint on window functions that
        they cannot be used in <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> or
        <a class="link" href="sql-statements.html#delete" title="13.2.2 DELETE Statement"><code class="literal">DELETE</code></a> statements to update rows.
        Using such functions in a subquery of these statements (to
        select rows) is permitted.
      </p><p>
        MySQL does not support these window function features:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            <code class="literal">DISTINCT</code> syntax for aggregate window
            functions.
          </p></li><li class="listitem"><p>
            Nested window functions.
          </p></li><li class="listitem"><p>
            Dynamic frame endpoints that depend on the value of the
            current row.
</p></li></ul>
</div>
<p>
        The parser recognizes these window constructs which nevertheless
        are not supported:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
            The <code class="literal">GROUPS</code> frame units specifier is
            parsed, but produces an error. Only <code class="literal">ROWS</code>
            and <code class="literal">RANGE</code> are supported.
          </p></li><li class="listitem"><p>
            The <code class="literal">EXCLUDE</code> clause for frame
            specification is parsed, but produces an error.
          </p></li><li class="listitem"><p>
            <code class="literal">IGNORE NULLS</code> is parsed, but produces an
            error. Only <code class="literal">RESPECT NULLS</code> is supported.
          </p></li><li class="listitem"><p>
            <code class="literal">FROM LAST</code> is parsed, but produces an
            error. Only <code class="literal">FROM FIRST</code> is supported.
</p></li></ul>
</div>

</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="performance-schema-functions"></a>12.22 Performance Schema Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444318204384"></a><a class="indexterm" name="idm46444318202896"></a><p>
      As of MySQL 8.0.16, MySQL includes built-in SQL functions that
      format or retrieve Performance Schema data, and that may be used
      as equivalents for the corresponding <code class="literal">sys</code> schema
      stored functions. The built-in functions can be invoked in any
      schema and require no qualifier, unlike the <code class="literal">sys</code>
      functions, which require either a <code class="literal">sys.</code> schema
      qualifier or that <code class="literal">sys</code> be the current schema.
</p>
<div class="table">
<a name="idm46444318198256"></a><p class="title"><b>Table 12.28 Performance Schema Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists Performance Schema functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_format-bytes"><code class="literal">FORMAT_BYTES()</code></a> (introduced 8.0.16)</td>
<td>
      Convert byte count to value with units
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_format-pico-time"><code class="literal">FORMAT_PICO_TIME()</code></a> (introduced 8.0.16)</td>
<td>
      Convert time in picoseconds to value with units
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ps-current-thread-id"><code class="literal">PS_CURRENT_THREAD_ID()</code></a> (introduced 8.0.16)</td>
<td>
      Performance Schema thread ID for current thread
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> (introduced 8.0.16)</td>
<td>
      Performance Schema thread ID for given thread
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      The built-in functions supersede the corresponding
      <code class="literal">sys</code> functions, which are deprecated and will be
      removed in a future MySQL version. Applications that use the
      <code class="literal">sys</code> functions should be adjusted to use the
      built-in functions instead, keeping in mind some minor differences
      between the <code class="literal">sys</code> functions and the built-in
      functions. For details about these differences, see the function
      descriptions in this section.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_format-bytes"></a><p>
          <a class="link" href="functions.html#function_format-bytes"><code class="literal">FORMAT_BYTES(<em class="replaceable"><code>count</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444318169552"></a><p>
          Given a numeric byte count, converts it to human-readable
          format and returns a string consisting of a value and a units
          indicator. The string contains the number of bytes rounded to
          2 decimal places and a minimum of 3 significant digits.
          Numbers less than 1024 bytes are represented as whole numbers
          and are not rounded.
        </p><p>
          The units indicator depends on the size of the byte-count
          argument as shown in the following table.
</p>
<div class="informaltable">
<table summary="Units indicators used by FORMAT_BYTES() function."><col width="30%"><col width="25%"><col width="45%"><thead><tr>
              <th scope="col">Argument Value</th>
              <th scope="col">Result Units</th>
              <th scope="col">Result Units Indicator</th>
            </tr></thead><tbody><tr>
              <td scope="row">Up to 1023</td>
              <td>bytes</td>
              <td>bytes</td>
            </tr><tr>
              <td scope="row">Up to 1024<sup>2</sup> − 1</td>
              <td>kibibytes</td>
              <td>KiB</td>
            </tr><tr>
              <td scope="row">Up to 1024<sup>3</sup> − 1</td>
              <td>mebibytes</td>
              <td>MiB</td>
            </tr><tr>
              <td scope="row">Up to 1024<sup>4</sup> − 1</td>
              <td>gibibytes</td>
              <td>GiB</td>
            </tr><tr>
              <td scope="row">Up to 1024<sup>5</sup> − 1</td>
              <td>tebibytes</td>
              <td>TiB</td>
            </tr><tr>
              <td scope="row">Up to 1024<sup>6</sup> − 1</td>
              <td>pebibytes</td>
              <td>PiB</td>
            </tr><tr>
              <td scope="row">1024<sup>6</sup> and up</td>
              <td>exbibytes</td>
              <td>EiB</td>
</tr></tbody></table>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FORMAT_BYTES(512), FORMAT_BYTES(18446644073709551615);</code></strong>
+-------------------+------------------------------------+
| FORMAT_BYTES(512) | FORMAT_BYTES(18446644073709551615) |
+-------------------+------------------------------------+
|  512 bytes        | 16.00 EiB                          |
+-------------------+------------------------------------+
</pre><p>
          <a class="link" href="functions.html#function_format-bytes"><code class="literal">FORMAT_BYTES()</code></a> was added in
          MySQL 8.0.16. It may be used instead of the
          <code class="literal">sys</code> schema
          <a class="link" href="sys-schema.html#sys-format-bytes" title="27.4.5.3 The format_bytes() Function"><code class="literal">format_bytes()</code></a> function, keeping
          in mind this difference:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              <a class="link" href="functions.html#function_format-bytes"><code class="literal">FORMAT_BYTES()</code></a> uses the
              <code class="literal">EiB</code> units indicator.
              <a class="link" href="sys-schema.html#sys-format-bytes" title="27.4.5.3 The format_bytes() Function"><code class="literal">sys.format_bytes()</code></a> does not.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_format-pico-time"></a><p>
          <a class="link" href="functions.html#function_format-pico-time"><code class="literal">FORMAT_PICO_TIME(<em class="replaceable"><code>time_val</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444318117296"></a><p>
          Given a numeric Performance Schema latency or wait time in
          picoseconds, converts it to human-readable format and returns
          a string consisting of a value and a units indicator. The
          string contains the decimal time rounded to 2 decimal places
          and a minimum of 3 significant digits. Times under 1
          nanosecond are represented as whole numbers and are not
          rounded.
        </p><p>
          The units indicator depends on the size of the time-value
          argument as shown in the following table.
</p>
<div class="informaltable">
<table summary="Units indicators used by FORMAT_PICO_TIME() function."><col width="30%"><col width="25%"><col width="45%"><thead><tr>
              <th scope="col">Argument Value</th>
              <th scope="col">Result Units</th>
              <th scope="col">Result Units Indicator</th>
            </tr></thead><tbody><tr>
              <td scope="row">Up to 10<sup>3</sup> − 1</td>
              <td>picoseconds</td>
              <td>ps</td>
            </tr><tr>
              <td scope="row">Up to 10<sup>6</sup> − 1</td>
              <td>nanoseconds</td>
              <td>ns</td>
            </tr><tr>
              <td scope="row">Up to 10<sup>9</sup> − 1</td>
              <td>microseconds</td>
              <td>us</td>
            </tr><tr>
              <td scope="row">Up to 10<sup>12</sup> − 1</td>
              <td>milliseconds</td>
              <td>ms</td>
            </tr><tr>
              <td scope="row">Up to 60×10<sup>12</sup> − 1</td>
              <td>seconds</td>
              <td>s</td>
            </tr><tr>
              <td scope="row">Up to 3.6×10<sup>15</sup> − 1</td>
              <td>minutes</td>
              <td>min</td>
            </tr><tr>
              <td scope="row">Up to 8.64×10<sup>16</sup> − 1</td>
              <td>hours</td>
              <td>h</td>
            </tr><tr>
              <td scope="row">8.64×10<sup>16</sup> and up</td>
              <td>days</td>
              <td>d</td>
</tr></tbody></table>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT FORMAT_PICO_TIME(3501), FORMAT_PICO_TIME(188732396662000);</code></strong>
+------------------------+-----------------------------------+
| FORMAT_PICO_TIME(3501) | FORMAT_PICO_TIME(188732396662000) |
+------------------------+-----------------------------------+
| 3.50 ns                | 3.15 min                          |
+------------------------+-----------------------------------+
</pre><p>
          <a class="link" href="functions.html#function_format-pico-time"><code class="literal">FORMAT_PICO_TIME()</code></a> was added in
          MySQL 8.0.16. It may be used instead of the
          <code class="literal">sys</code> schema
          <a class="link" href="sys-schema.html#sys-format-time" title="27.4.5.6 The format_time() Function"><code class="literal">format_time()</code></a> function, keeping
          in mind these differences:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              To indicate minutes,
              <a class="link" href="sys-schema.html#sys-format-time" title="27.4.5.6 The format_time() Function"><code class="literal">sys.format_time()</code></a> uses the
              <code class="literal">m</code> units indicator, whereas
              <a class="link" href="functions.html#function_format-pico-time"><code class="literal">FORMAT_PICO_TIME()</code></a> uses
              <code class="literal">min</code>.
            </p></li><li class="listitem"><p>
              <a class="link" href="sys-schema.html#sys-format-time" title="27.4.5.6 The format_time() Function"><code class="literal">sys.format_time()</code></a> uses the
              <code class="literal">w</code> (weeks) units indicator.
              <a class="link" href="functions.html#function_format-pico-time"><code class="literal">FORMAT_PICO_TIME()</code></a> does
              not.
</p></li></ul>
</div>
</li><li class="listitem"><a name="function_ps-current-thread-id"></a><p>
          <a class="link" href="functions.html#function_ps-current-thread-id"><code class="literal">PS_CURRENT_THREAD_ID()</code></a>
        </p><a class="indexterm" name="idm46444318056544"></a><p>
          Returns a <code class="literal">BIGINT UNSIGNED</code> value
          representing the Performance Schema thread ID assigned to the
          current connection.
        </p><p>
          The thread ID return value is a value of the type given in the
          <code class="literal">THREAD_ID</code> column of Performance Schema
          tables.
        </p><p>
          Performance Schema configuration affects
          <a class="link" href="functions.html#function_ps-current-thread-id"><code class="literal">PS_CURRENT_THREAD_ID()</code></a> the same
          way as for <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a>. For
          details, see the description of that function.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT PS_CURRENT_THREAD_ID();</code></strong>
+------------------------+
| PS_CURRENT_THREAD_ID() |
+------------------------+
|                     52 |
+------------------------+
mysql&gt; <strong class="userinput"><code>SELECT PS_THREAD_ID(CONNECTION_ID());</code></strong>
+-------------------------------+
| PS_THREAD_ID(CONNECTION_ID()) |
+-------------------------------+
|                            52 |
+-------------------------------+
</pre><p>
          <a class="link" href="functions.html#function_ps-current-thread-id"><code class="literal">PS_CURRENT_THREAD_ID()</code></a> was
          added in MySQL 8.0.16. It may be used as a shortcut for
          invoking the <code class="literal">sys</code> schema
          <a class="link" href="sys-schema.html#sys-ps-thread-id" title="27.4.5.15 The ps_thread_id() Function"><code class="literal">ps_thread_id()</code></a> function with an
          argument of <code class="literal">NULL</code> or
          <a class="link" href="functions.html#function_connection-id"><code class="literal">CONNECTION_ID()</code></a>.
        </p></li><li class="listitem"><a name="function_ps-thread-id"></a><p>
          <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID(<em class="replaceable"><code>connection_id</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444318034976"></a><p>
          Given a connection ID, returns a <code class="literal">BIGINT
          UNSIGNED</code> value representing the Performance Schema
          thread ID assigned to the connection ID, or
          <code class="literal">NULL</code> if no thread ID exists for the
          connection ID. The latter can occur for threads that are not
          instrumented.
        </p><p>
          The connection ID argument is a value of the type given in the
          <code class="literal">PROCESSLIST_ID</code> column of the Performance
          Schema <a class="link" href="performance-schema.html#threads-table" title="26.12.19.5 The threads Table"><code class="literal">threads</code></a> table or the
          <code class="literal">Id</code> column of <a class="link" href="sql-statements.html#show-processlist" title="13.7.7.29 SHOW PROCESSLIST Statement"><code class="literal">SHOW
          PROCESSLIST</code></a> output.
        </p><p>
          The thread ID return value is a value of the type given in the
          <code class="literal">THREAD_ID</code> column of Performance Schema
          tables.
        </p><p>
          Performance Schema configuration affects
          <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> operation as
          follows. (These remarks also apply to
          <a class="link" href="functions.html#function_ps-current-thread-id"><code class="literal">PS_CURRENT_THREAD_ID()</code></a>.)
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Disabling the <code class="literal">thread_instrumentation</code>
              consumer disables statistics from being collected and
              aggregated at the thread level, but has no effect on
              <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a>.
            </p></li><li class="listitem"><p>
              If
              <a class="link" href="performance-schema.html#sysvar_performance_schema_max_thread_instances"><code class="literal">performance_schema_max_thread_instances</code></a>
              is not 0, the Performance Schema allocates memory for
              thread statistics and assigns an internal ID to each
              thread for which instance memory is available. If there
              are threads for which instance memory is not available,
              <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> returns
              <code class="literal">NULL</code>; in this case,
              <a class="link" href="performance-schema.html#statvar_Performance_schema_thread_instances_lost"><code class="literal">Performance_schema_thread_instances_lost</code></a>
              will be nonzero.
            </p></li><li class="listitem"><p>
              If
              <a class="link" href="performance-schema.html#sysvar_performance_schema_max_thread_instances"><code class="literal">performance_schema_max_thread_instances</code></a>
              is 0, the Performance Schema allocates no thread memory
              and <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> returns
              <code class="literal">NULL</code>.
            </p></li><li class="listitem"><p>
              If the Performance Schema itself is disabled,
              <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> produces an
              error.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT PS_THREAD_ID(6);</code></strong>
+-----------------+
| PS_THREAD_ID(6) |
+-----------------+
|              45 |
+-----------------+
</pre><p>
          <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> was added in
          MySQL 8.0.16. It may be used instead of the
          <code class="literal">sys</code> schema
          <a class="link" href="sys-schema.html#sys-ps-thread-id" title="27.4.5.15 The ps_thread_id() Function"><code class="literal">ps_thread_id()</code></a> function, keeping
          in mind this difference:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              With an argument of <code class="literal">NULL</code>,
              <a class="link" href="sys-schema.html#sys-ps-thread-id" title="27.4.5.15 The ps_thread_id() Function"><code class="literal">sys.ps_thread_id()</code></a> returns
              the thread ID for the current connection, whereas
              <a class="link" href="functions.html#function_ps-thread-id"><code class="literal">PS_THREAD_ID()</code></a> returns
              <code class="literal">NULL</code>. To obtain the current connection
              thread ID, use
              <a class="link" href="functions.html#function_ps-current-thread-id"><code class="literal">PS_CURRENT_THREAD_ID()</code></a>
              instead.
</p></li></ul>
</div>
</li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="internal-functions"></a>12.23 Internal Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444317992800"></a><a class="indexterm" name="idm46444317991728"></a>
<div class="table">
<a name="idm46444317990240"></a><p class="title"><b>Table 12.29 Internal Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists functions intended only for internal use by the server."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_can-access-column"><code class="literal">CAN_ACCESS_COLUMN()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_can-access-database"><code class="literal">CAN_ACCESS_DATABASE()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_can-access-table"><code class="literal">CAN_ACCESS_TABLE()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_can-access-view"><code class="literal">CAN_ACCESS_VIEW()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-dd-column-privileges"><code class="literal">GET_DD_COLUMN_PRIVILEGES()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-dd-create-options"><code class="literal">GET_DD_CREATE_OPTIONS()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_get-dd-index-sub-part-length"><code class="literal">GET_DD_INDEX_SUB_PART_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-auto-increment"><code class="literal">INTERNAL_AUTO_INCREMENT()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-avg-row-length"><code class="literal">INTERNAL_AVG_ROW_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-check-time"><code class="literal">INTERNAL_CHECK_TIME()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-checksum"><code class="literal">INTERNAL_CHECKSUM()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-data-free"><code class="literal">INTERNAL_DATA_FREE()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-data-length"><code class="literal">INTERNAL_DATA_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-dd-char-length"><code class="literal">INTERNAL_DD_CHAR_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-comment-or-error"><code class="literal">INTERNAL_GET_COMMENT_OR_ERROR()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-enabled-role-json"><code class="literal">INTERNAL_GET_ENABLED_ROLE_JSON()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-hostname"><code class="literal">INTERNAL_GET_HOSTNAME()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-username"><code class="literal">INTERNAL_GET_USERNAME()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-get-view-warning-or-error"><code class="literal">INTERNAL_GET_VIEW_WARNING_OR_ERROR()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-index-column-cardinality"><code class="literal">INTERNAL_INDEX_COLUMN_CARDINALITY()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-index-length"><code class="literal">INTERNAL_INDEX_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-is-enabled-role"><code class="literal">INTERNAL_IS_ENABLED_ROLE()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-is-mandatory-role"><code class="literal">INTERNAL_IS_MANDATORY_ROLE()</code></a> (introduced 8.0.19)</td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-keys-disabled"><code class="literal">INTERNAL_KEYS_DISABLED()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-max-data-length"><code class="literal">INTERNAL_MAX_DATA_LENGTH()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-table-rows"><code class="literal">INTERNAL_TABLE_ROWS()</code></a></td>
<td>
      Internal use only
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_internal-update-time"><code class="literal">INTERNAL_UPDATE_TIME()</code></a></td>
<td>
      Internal use only
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break"><p>
      The functions listed in this section are intended only for
      internal use by the server. Attempts by users to invoke them
      result in an error.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_can-access-column"></a><p>
          <a class="link" href="functions.html#function_can-access-column"><code class="literal">CAN_ACCESS_COLUMN(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317888624"></a></li><li class="listitem"><a name="function_can-access-database"></a><p>
          <a class="link" href="functions.html#function_can-access-database"><code class="literal">CAN_ACCESS_DATABASE(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317882112"></a></li><li class="listitem"><a name="function_can-access-table"></a><p>
          <a class="link" href="functions.html#function_can-access-table"><code class="literal">CAN_ACCESS_TABLE(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317875600"></a></li><li class="listitem"><a name="function_can-access-view"></a><p>
          <a class="link" href="functions.html#function_can-access-view"><code class="literal">CAN_ACCESS_VIEW(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317869088"></a></li><li class="listitem"><a name="function_get-dd-column-privileges"></a><p>
          <a class="link" href="functions.html#function_get-dd-column-privileges"><code class="literal">GET_DD_COLUMN_PRIVILEGES(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317862576"></a></li><li class="listitem"><a name="function_get-dd-create-options"></a><p>
          <a class="link" href="functions.html#function_get-dd-create-options"><code class="literal">GET_DD_CREATE_OPTIONS(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317855984"></a></li><li class="listitem"><a name="function_get-dd-index-sub-part-length"></a><p>
          <a class="link" href="functions.html#function_get-dd-index-sub-part-length"><code class="literal">GET_DD_INDEX_SUB_PART_LENGTH(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317849472"></a></li><li class="listitem"><a name="function_internal-auto-increment"></a><p>
          <a class="link" href="functions.html#function_internal-auto-increment"><code class="literal">INTERNAL_AUTO_INCREMENT(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317842912"></a></li><li class="listitem"><a name="function_internal-avg-row-length"></a><p>
          <a class="link" href="functions.html#function_internal-avg-row-length"><code class="literal">INTERNAL_AVG_ROW_LENGTH(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317836352"></a></li><li class="listitem"><a name="function_internal-check-time"></a><p>
          <a class="link" href="functions.html#function_internal-check-time"><code class="literal">INTERNAL_CHECK_TIME(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317829776"></a></li><li class="listitem"><a name="function_internal-checksum"></a><p>
          <a class="link" href="functions.html#function_internal-checksum"><code class="literal">INTERNAL_CHECKSUM(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317823264"></a></li><li class="listitem"><a name="function_internal-data-free"></a><p>
          <a class="link" href="functions.html#function_internal-data-free"><code class="literal">INTERNAL_DATA_FREE(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317816752"></a></li><li class="listitem"><a name="function_internal-data-length"></a><p>
          <a class="link" href="functions.html#function_internal-data-length"><code class="literal">INTERNAL_DATA_LENGTH(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317810224"></a></li><li class="listitem"><a name="function_internal-dd-char-length"></a><p>
          <a class="link" href="functions.html#function_internal-dd-char-length"><code class="literal">INTERNAL_DD_CHAR_LENGTH(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317803728"></a></li><li class="listitem"><a name="function_internal-get-comment-or-error"></a><p>
          <a class="link" href="functions.html#function_internal-get-comment-or-error"><code class="literal">INTERNAL_GET_COMMENT_OR_ERROR(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317797152"></a></li><li class="listitem"><a name="function_internal-get-enabled-role-json"></a><p>
          <a class="link" href="functions.html#function_internal-get-enabled-role-json"><code class="literal">INTERNAL_GET_ENABLED_ROLE_JSON(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317790576"></a></li><li class="listitem"><a name="function_internal-get-hostname"></a><p>
          <a class="link" href="functions.html#function_internal-get-hostname"><code class="literal">INTERNAL_GET_HOSTNAME(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317783968"></a></li><li class="listitem"><a name="function_internal-get-username"></a><p>
          <a class="link" href="functions.html#function_internal-get-username"><code class="literal">INTERNAL_GET_USERNAME(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317777488"></a></li><li class="listitem"><a name="function_internal-get-view-warning-or-error"></a><p>
          <a class="link" href="functions.html#function_internal-get-view-warning-or-error"><code class="literal">INTERNAL_GET_VIEW_WARNING_OR_ERROR(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317770832"></a></li><li class="listitem"><a name="function_internal-index-column-cardinality"></a><p>
          <a class="link" href="functions.html#function_internal-index-column-cardinality"><code class="literal">INTERNAL_INDEX_COLUMN_CARDINALITY(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317764256"></a></li><li class="listitem"><a name="function_internal-index-length"></a><p>
          <a class="link" href="functions.html#function_internal-index-length"><code class="literal">INTERNAL_INDEX_LENGTH(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317757728"></a></li><li class="listitem"><a name="function_internal-is-enabled-role"></a><p>
          <a class="link" href="functions.html#function_internal-is-enabled-role"><code class="literal">INTERNAL_IS_ENABLED_ROLE(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317751216"></a></li><li class="listitem"><a name="function_internal-is-mandatory-role"></a><p>
          <a class="link" href="functions.html#function_internal-is-mandatory-role"><code class="literal">INTERNAL_IS_MANDATORY_ROLE(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317744640"></a></li><li class="listitem"><a name="function_internal-keys-disabled"></a><p>
          <a class="link" href="functions.html#function_internal-keys-disabled"><code class="literal">INTERNAL_KEYS_DISABLED(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317738048"></a></li><li class="listitem"><a name="function_internal-max-data-length"></a><p>
          <a class="link" href="functions.html#function_internal-max-data-length"><code class="literal">INTERNAL_MAX_DATA_LENGTH(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317731520"></a></li><li class="listitem"><a name="function_internal-table-rows"></a><p>
          <a class="link" href="functions.html#function_internal-table-rows"><code class="literal">INTERNAL_TABLE_ROWS(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317724944"></a></li><li class="listitem"><a name="function_internal-update-time"></a><p>
          <a class="link" href="functions.html#function_internal-update-time"><code class="literal">INTERNAL_UPDATE_TIME(<em class="replaceable"><code>ARGS</code></em>)</code></a>
        </p><a class="indexterm" name="idm46444317718480"></a></li><li class="listitem"><a name="function_is-visible-dd-object"></a><p>
          <a class="link" href="functions.html#function_is-visible-dd-object"><code class="literal">IS_VISIBLE_DD_OBJECT(<em class="replaceable"><code>ARGS</code></em>)</code></a>
</p><a class="indexterm" name="idm46444317711888"></a></li></ul>
</div>

</div>

<div class="section">

<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="miscellaneous-functions"></a>12.24 Miscellaneous Functions</h2>

</div>

</div>

</div>
<a class="indexterm" name="idm46444317708800"></a><a class="indexterm" name="idm46444317707728"></a>
<div class="table">
<a name="idm46444317706240"></a><p class="title"><b>Table 12.30 Miscellaneous Functions</b></p>
<div class="table-contents">
<table frame="box" rules="all" summary="A reference that lists miscellaneous functions."><col width="40%"><col width="60%"><thead><tr><th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead><tbody><tr><td scope="row"><a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a></td>
<td>
      Suppress ONLY_FULL_GROUP_BY value rejection
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a></td>
<td>
      Convert binary UUID to string
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_default"><code class="literal">DEFAULT()</code></a></td>
<td>
      Return the default value for a table column
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a></td>
<td>
      Distinguish super-aggregate ROLLUP rows from regular rows
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a></td>
<td>
      Return the numeric value of an IP address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet-ntoa"><code class="literal">INET_NTOA()</code></a></td>
<td>
      Return the IP address from a numeric value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a></td>
<td>
      Return the numeric value of an IPv6 address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_inet6-ntoa"><code class="literal">INET6_NTOA()</code></a></td>
<td>
      Return the IPv6 address from a numeric value
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv4"><code class="literal">IS_IPV4()</code></a></td>
<td>
      Whether argument is an IPv4 address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv4-compat"><code class="literal">IS_IPV4_COMPAT()</code></a></td>
<td>
      Whether argument is an IPv4-compatible address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv4-mapped"><code class="literal">IS_IPV4_MAPPED()</code></a></td>
<td>
      Whether argument is an IPv4-mapped address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-ipv6"><code class="literal">IS_IPV6()</code></a></td>
<td>
      Whether argument is an IPv6 address
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_is-uuid"><code class="literal">IS_UUID()</code></a></td>
<td>
      Whether argument is a valid UUID
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_master-pos-wait"><code class="literal">MASTER_POS_WAIT()</code></a></td>
<td>
      Block until the slave has read and applied all updates up to the
      specified position
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_name-const"><code class="literal">NAME_CONST()</code></a></td>
<td>
      Cause the column to have the given name
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_sleep"><code class="literal">SLEEP()</code></a></td>
<td>
      Sleep for a number of seconds
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a></td>
<td>
      Return a Universal Unique Identifier (UUID)
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a></td>
<td>
      Return an integer-valued universal identifier
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a></td>
<td>
      Convert string UUID to binary
    </td>
</tr><tr><td scope="row"><a class="link" href="functions.html#function_values"><code class="literal">VALUES()</code></a></td>
<td>
      Define the values to be used during an INSERT
    </td>
</tr></tbody></table>
</div>

</div>
<br class="table-break">
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a name="function_any-value"></a><p>
          <a class="indexterm" name="idm46444317631088"></a>

          <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE(<em class="replaceable"><code>arg</code></em>)</code></a>
        </p><p>
          This function is useful for <code class="literal">GROUP BY</code>
          queries when the
          <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> SQL mode
          is enabled, for cases when MySQL rejects a query that you know
          is valid for reasons that MySQL cannot determine. The function
          return value and type are the same as the return value and
          type of its argument, but the function result is not checked
          for the <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a>
          SQL mode.
        </p><p>
          For example, if <code class="literal">name</code> is a nonindexed
          column, the following query fails with
          <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> enabled:
        </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT name, address, MAX(age) FROM t GROUP BY name;</code></strong>
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP
BY clause and contains nonaggregated column 'mydb.t.address' which
is not functionally dependent on columns in GROUP BY clause; this
is incompatible with sql_mode=only_full_group_by
</pre><p>
          The failure occurs because <code class="literal">address</code> is a
          nonaggregated column that is neither named among
          <code class="literal">GROUP BY</code> columns nor functionally dependent
          on them. As a result, the <code class="literal">address</code> value for
          rows within each <code class="literal">name</code> group is
          nondeterministic. There are multiple ways to cause MySQL to
          accept the query:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Alter the table to make <code class="literal">name</code> a primary
              key or a unique <code class="literal">NOT NULL</code> column. This
              enables MySQL to determine that <code class="literal">address</code>
              is functionally dependent on <code class="literal">name</code>; that
              is, <code class="literal">address</code> is uniquely determined by
              <code class="literal">name</code>. (This technique is inapplicable
              if <code class="literal">NULL</code> must be permitted as a valid
              <code class="literal">name</code> value.)
            </p></li><li class="listitem"><p>
              Use <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> to refer to
              <code class="literal">address</code>:
            </p><pre data-lang="sql" class="programlisting">SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;</pre><p>
              In this case, MySQL ignores the nondeterminism of
              <code class="literal">address</code> values within each
              <code class="literal">name</code> group and accepts the query. This
              may be useful if you simply do not care which value of a
              nonaggregated column is chosen for each group.
              <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> is not an
              aggregate function, unlike functions such as
              <a class="link" href="functions.html#function_sum"><code class="literal">SUM()</code></a> or
              <a class="link" href="functions.html#function_count"><code class="literal">COUNT()</code></a>. It simply acts to
              suppress the test for nondeterminism.
            </p></li><li class="listitem"><p>
              Disable
              <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a>. This
              is equivalent to using
              <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> with
              <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a>
              enabled, as described in the previous item.
</p></li></ul>
</div>
<p>
          <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> is also useful if
          functional dependence exists between columns but MySQL cannot
          determine it. The following query is valid because
          <code class="literal">age</code> is functionally dependent on the
          grouping column <code class="literal">age-1</code>, but MySQL cannot
          tell that and rejects the query with
          <a class="link" href="server-administration.html#sqlmode_only_full_group_by"><code class="literal">ONLY_FULL_GROUP_BY</code></a> enabled:
        </p><pre data-lang="sql" class="programlisting">SELECT age FROM t GROUP BY age-1;</pre><p>
          To cause MySQL to accept the query, use
          <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a>:
        </p><pre data-lang="sql" class="programlisting">SELECT ANY_VALUE(age) FROM t GROUP BY age-1;</pre><p>
          <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> can be used for
          queries that refer to aggregate functions in the absence of a
          <code class="literal">GROUP BY</code> clause:
        </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT name, MAX(age) FROM t;</code></strong>
ERROR 1140 (42000): In aggregated query without GROUP BY, expression
#1 of SELECT list contains nonaggregated column 'mydb.t.name'; this
is incompatible with sql_mode=only_full_group_by
</pre><p>
          Without <code class="literal">GROUP BY</code>, there is a single group
          and it is nondeterministic which <code class="literal">name</code> value
          to choose for the group.
          <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> tells MySQL to
          accept the query:
        </p><pre data-lang="sql" class="programlisting">SELECT ANY_VALUE(name), MAX(age) FROM t;</pre><p>
          It may be that, due to some property of a given data set, you
          know that a selected nonaggregated column is effectively
          functionally dependent on a <code class="literal">GROUP BY</code>
          column. For example, an application may enforce uniqueness of
          one column with respect to another. In this case, using
          <a class="link" href="functions.html#function_any-value"><code class="literal">ANY_VALUE()</code></a> for the effectively
          functionally dependent column may make sense.
        </p><p>
          For additional discussion, see
          <a class="xref" href="functions.html#group-by-handling" title="12.20.3 MySQL Handling of GROUP BY">Section 12.20.3, “MySQL Handling of GROUP BY”</a>.
        </p></li><li class="listitem"><a name="function_bin-to-uuid"></a><p>
          <a class="indexterm" name="idm46444317570784"></a>

          <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID(<em class="replaceable"><code>binary_uuid</code></em>)</code></a>,
          <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID(<em class="replaceable"><code>binary_uuid</code></em>,
          <em class="replaceable"><code>swap_flag</code></em>)</code></a>
        </p><p>
          <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a> is the inverse of
          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a>. It converts a
          binary UUID to a string UUID and returns the result. The
          binary value should be a UUID as a
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY(16)</code></a> value. The return
          value is a <code class="literal">utf8</code> string of five hexadecimal
          numbers separated by dashes. (For details about this format,
          see the <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> function
          description.) If the UUID argument is <code class="literal">NULL</code>,
          the return value is <code class="literal">NULL</code>. If any argument
          is invalid, an error occurs.
        </p><p>
          <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a> takes one or two
          arguments:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The one-argument form takes a binary UUID value. The UUID
              value is assumed not to have its time-low and time-high
              parts swapped. The string result is in the same order as
              the binary argument.
            </p></li><li class="listitem"><p>
              The two-argument form takes a binary UUID value and a
              swap-flag value:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  If <em class="replaceable"><code>swap_flag</code></em> is 0, the
                  two-argument form is equivalent to the one-argument
                  form. The string result is in the same order as the
                  binary argument.
                </p></li><li class="listitem"><p>
                  If <em class="replaceable"><code>swap_flag</code></em> is 1, the UUID
                  value is assumed to have its time-low and time-high
                  parts swapped. These parts are swapped back to their
                  original position in the result value.
</p></li></ul>
</div>
</li></ul>
</div>
<p>
          For usage examples and information about time-part swapping,
          see the <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a> function
          description.
        </p></li><li class="listitem"><a name="function_default"></a><p>
          <a class="indexterm" name="idm46444317546144"></a>

          <a class="link" href="functions.html#function_default"><code class="literal">DEFAULT(<em class="replaceable"><code>col_name</code></em>)</code></a>
        </p><p>
          Returns the default value for a table column. An error results
          if the column has no default value.
        </p><p>
          The use of
          <a class="link" href="functions.html#function_default"><code class="literal">DEFAULT(<em class="replaceable"><code>col_name</code></em>)</code></a>
          to specify the default value for a named column is permitted
          only for columns that have a literal default value, not for
          columns that have an expression default value.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>UPDATE t SET i = DEFAULT(i)+1 WHERE id &lt; 100;</code></strong>
</pre></li><li class="listitem"><p>
          <a class="link" href="functions.html#function_format"><code class="literal">FORMAT(<em class="replaceable"><code>X</code></em>,<em class="replaceable"><code>D</code></em>)</code></a>
        </p><p>
          Formats the number <em class="replaceable"><code>X</code></em> to a format
          like <code class="literal">'#,###,###.##'</code>, rounded to
          <em class="replaceable"><code>D</code></em> decimal places, and returns the
          result as a string. For details, see
          <a class="xref" href="functions.html#string-functions" title="12.7 String Functions and Operators">Section 12.7, “String Functions and Operators”</a>.
        </p></li><li class="listitem"><a name="function_grouping"></a><p>
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING(<em class="replaceable"><code>expr</code></em>
          [, <em class="replaceable"><code>expr</code></em>] ...)</code></a>
        </p><a class="indexterm" name="idm46444317525104"></a><p>
          For <code class="literal">GROUP BY</code> queries that include a
          <code class="literal">WITH ROLLUP</code> modifier, the
          <code class="literal">ROLLUP</code> operation produces super-aggregate
          output rows where <code class="literal">NULL</code> represents the set
          of all values. The <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>
          function enables you to distinguish <code class="literal">NULL</code>
          values for super-aggregate rows from <code class="literal">NULL</code>
          values in regular grouped rows.
        </p><p>
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> is permitted only in
          the select list or <code class="literal">HAVING</code> clause.
        </p><p>
          Each argument to <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>
          must be an expression that exactly matches an expression in
          the <code class="literal">GROUP BY</code> clause. The expression cannot
          be a positional specifier. For each expression,
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> produces 1 if the
          expression value in the current row is a
          <code class="literal">NULL</code> representing a super-aggregate value.
          Otherwise, <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> produces
          0, indicating that the expression value is a
          <code class="literal">NULL</code> for a regular result row or is not
          <code class="literal">NULL</code>.
        </p><p>
          Suppose that table <code class="literal">t1</code> contains these rows,
          where <code class="literal">NULL</code> indicates something like
          <span class="quote">“<span class="quote">other</span>”</span> or <span class="quote">“<span class="quote">unknown</span>”</span>:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT * FROM t1;</code></strong>
+------+-------+----------+
| name | size  | quantity |
+------+-------+----------+
| ball | small |       10 |
| ball | large |       20 |
| ball | NULL  |        5 |
| hoop | small |       15 |
| hoop | large |        5 |
| hoop | NULL  |        3 |
+------+-------+----------+
</pre><p>
          A summary of the table without <code class="literal">WITH ROLLUP</code>
          looks like this:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT name, size, SUM(quantity) AS quantity</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size;</code></strong>
+------+-------+----------+
| name | size  | quantity |
+------+-------+----------+
| ball | small |       10 |
| ball | large |       20 |
| ball | NULL  |        5 |
| hoop | small |       15 |
| hoop | large |        5 |
| hoop | NULL  |        3 |
+------+-------+----------+
</pre><p>
          The result contains <code class="literal">NULL</code> values, but those
          do not represent super-aggregate rows because the query does
          not include <code class="literal">WITH ROLLUP</code>.
        </p><p>
          Adding <code class="literal">WITH ROLLUP</code> produces super-aggregate
          summary rows containing additional <code class="literal">NULL</code>
          values. However, without comparing this result to the previous
          one, it is not easy to see which <code class="literal">NULL</code>
          values occur in super-aggregate rows and which occur in
          regular grouped rows:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT name, size, SUM(quantity) AS quantity</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP;</code></strong>
+------+-------+----------+
| name | size  | quantity |
+------+-------+----------+
| ball | NULL  |        5 |
| ball | large |       20 |
| ball | small |       10 |
| ball | NULL  |       35 |
| hoop | NULL  |        3 |
| hoop | large |        5 |
| hoop | small |       15 |
| hoop | NULL  |       23 |
| NULL | NULL  |       58 |
+------+-------+----------+
</pre><p>
          To distinguish <code class="literal">NULL</code> values in
          super-aggregate rows from those in regular grouped rows, use
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>, which returns 1
          only for super-aggregate <code class="literal">NULL</code> values:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>name, size, SUM(quantity) AS quantity,</code></strong>
         <strong class="userinput"><code>GROUPING(name) AS grp_name,</code></strong>
         <strong class="userinput"><code>GROUPING(size) AS grp_size</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP;</code></strong>
+------+-------+----------+----------+----------+
| name | size  | quantity | grp_name | grp_size |
+------+-------+----------+----------+----------+
| ball | NULL  |        5 |        0 |        0 |
| ball | large |       20 |        0 |        0 |
| ball | small |       10 |        0 |        0 |
| ball | NULL  |       35 |        0 |        1 |
| hoop | NULL  |        3 |        0 |        0 |
| hoop | large |        5 |        0 |        0 |
| hoop | small |       15 |        0 |        0 |
| hoop | NULL  |       23 |        0 |        1 |
| NULL | NULL  |       58 |        1 |        1 |
+------+-------+----------+----------+----------+
</pre><p>
          Common uses for <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Substitute a label for super-aggregate
              <code class="literal">NULL</code> values:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>IF(GROUPING(name) = 1, 'All items', name) AS name,</code></strong>
         <strong class="userinput"><code>IF(GROUPING(size) = 1, 'All sizes', size) AS size,</code></strong>
         <strong class="userinput"><code>SUM(quantity) AS quantity</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP;</code></strong>
+-----------+-----------+----------+
| name      | size      | quantity |
+-----------+-----------+----------+
| ball      | NULL      |        5 |
| ball      | large     |       20 |
| ball      | small     |       10 |
| ball      | All sizes |       35 |
| hoop      | NULL      |        3 |
| hoop      | large     |        5 |
| hoop      | small     |       15 |
| hoop      | All sizes |       23 |
| All items | All sizes |       58 |
+-----------+-----------+----------+
</pre></li><li class="listitem"><p>
              Return only super-aggregate lines by filtering out the
              regular grouped lines:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT name, size, SUM(quantity) AS quantity</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP</code></strong>
       <strong class="userinput"><code>HAVING GROUPING(name) = 1 OR GROUPING(size) = 1;</code></strong>
+------+------+----------+
| name | size | quantity |
+------+------+----------+
| ball | NULL |       35 |
| hoop | NULL |       23 |
| NULL | NULL |       58 |
+------+------+----------+
</pre></li></ul>
</div>
<p>
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> permits multiple
          expression arguments. In this case, the
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> return value
          represents a bitmask combined from the results for each
          expression, where the lowest-order bit corresponds to the
          result for the rightmost expression. For example, with three
          expression arguments,
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING(<em class="replaceable"><code>expr1</code></em>,
          <em class="replaceable"><code>expr2</code></em>,
          <em class="replaceable"><code>expr3</code></em>)</code></a> is evaluated like
          this:
        </p><pre data-lang="clike" class="programlisting">  result for GROUPING(<em class="replaceable"><code>expr3</code></em>)
+ result for GROUPING(<em class="replaceable"><code>expr2</code></em>) &lt;&lt; 1
+ result for GROUPING(<em class="replaceable"><code>expr1</code></em>) &lt;&lt; 2
</pre><p>
          The following query shows how
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> results for single
          arguments combine for a multiple-argument call to produce a
          bitmask value:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
         <strong class="userinput"><code>name, size, SUM(quantity) AS quantity,</code></strong>
         <strong class="userinput"><code>GROUPING(name) AS grp_name,</code></strong>
         <strong class="userinput"><code>GROUPING(size) AS grp_size,</code></strong>
       <strong class="userinput"><code>GROUPING(name, size) AS grp_all</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP;</code></strong>
+------+-------+----------+----------+----------+---------+
| name | size  | quantity | grp_name | grp_size | grp_all |
+------+-------+----------+----------+----------+---------+
| ball | NULL  |        5 |        0 |        0 |       0 |
| ball | large |       20 |        0 |        0 |       0 |
| ball | small |       10 |        0 |        0 |       0 |
| ball | NULL  |       35 |        0 |        1 |       1 |
| hoop | NULL  |        3 |        0 |        0 |       0 |
| hoop | large |        5 |        0 |        0 |       0 |
| hoop | small |       15 |        0 |        0 |       0 |
| hoop | NULL  |       23 |        0 |        1 |       1 |
| NULL | NULL  |       58 |        1 |        1 |       3 |
+------+-------+----------+----------+----------+---------+
</pre><p>
          With multiple expression arguments, the
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> return value is
          nonzero if any expression represents a super-aggregate value.
          Multiple-argument <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>
          syntax thus provides a simpler way to write the earlier query
          that returned only super-aggregate rows, by using a single
          multiple-argument <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>
          call rather than multiple single-argument calls:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT name, size, SUM(quantity) AS quantity</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY name, size WITH ROLLUP</code></strong>
       <strong class="userinput"><code>HAVING GROUPING(name, size) &lt;&gt; 0;</code></strong>
+------+------+----------+
| name | size | quantity |
+------+------+----------+
| ball | NULL |       35 |
| hoop | NULL |       23 |
| NULL | NULL |       58 |
+------+------+----------+
</pre><p>
          Use of <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> is subject to
          these limitations:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              Do not use subquery <code class="literal">GROUP BY</code>
              expressions as <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>
              arguments because matching might fail. For example,
              matching fails for this query:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT GROUPING((SELECT MAX(name) FROM t1))</code></strong>
       <strong class="userinput"><code>FROM t1</code></strong>
       <strong class="userinput"><code>GROUP BY (SELECT MAX(name) FROM t1) WITH ROLLUP;</code></strong>
ERROR 3580 (HY000): Argument #1 of GROUPING function is not in GROUP BY
</pre></li><li class="listitem"><p>
              <code class="literal">GROUP BY</code> literal expressions should not
              be used within a <code class="literal">HAVING</code> clause as
              <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> arguments. Due
              to differences between when the optimizer evaluates
              <code class="literal">GROUP BY</code> and <code class="literal">HAVING</code>,
              matching may succeed but
              <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> evaluation does
              not produce the expected result. Consider this query:
            </p><pre data-lang="sql" class="programlisting">SELECT a AS f1, 'w' AS f2
FROM t
GROUP BY f1, f2 WITH ROLLUP
HAVING GROUPING(f2) = 1;</pre><p>
              <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a> is evaluated
              earlier for the literal constant expression than for the
              <code class="literal">HAVING</code> clause as a whole and returns 0.
              To check whether a query such as this is affected, use
              <a class="link" href="sql-statements.html#explain" title="13.8.2 EXPLAIN Statement"><code class="literal">EXPLAIN</code></a> and look for
              <code class="literal">Impossible having</code> in the
              <code class="literal">Extra</code> column.
</p></li></ul>
</div>
<p>
          For more information about <code class="literal">WITH ROLLUP</code> and
          <a class="link" href="functions.html#function_grouping"><code class="literal">GROUPING()</code></a>, see
          <a class="xref" href="functions.html#group-by-modifiers" title="12.20.2 GROUP BY Modifiers">Section 12.20.2, “GROUP BY Modifiers”</a>.
        </p></li><li class="listitem"><a name="function_inet-aton"></a><p>
          <a class="indexterm" name="idm46444317415648"></a>

          <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Given the dotted-quad representation of an IPv4 network
          address as a string, returns an integer that represents the
          numeric value of the address in network byte order (big
          endian). <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a> returns
          <code class="literal">NULL</code> if it does not understand its
          argument.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT INET_ATON('10.0.5.9');</code></strong>
        -&gt; 167773449
</pre><p>
          For this example, the return value is calculated as
          10×256<sup>3</sup> +
          0×256<sup>2</sup> + 5×256 + 9.
        </p><p>
          <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a> may or may not
          return a non-<code class="literal">NULL</code> result for short-form IP
          addresses (such as <code class="literal">'127.1'</code> as a
          representation of <code class="literal">'127.0.0.1'</code>). Because of
          this, <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a>a should not
          be used for such addresses.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            To store values generated by
            <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a>, use an
            <code class="literal">INT UNSIGNED</code> column rather than
            <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a>, which is signed. If you
            use a signed column, values corresponding to IP addresses
            for which the first octet is greater than 127 cannot be
            stored correctly. See
            <a class="xref" href="data-types.html#out-of-range-and-overflow" title="11.1.7 Out-of-Range and Overflow Handling">Section 11.1.7, “Out-of-Range and Overflow Handling”</a>.
</p>
</div>
</li><li class="listitem"><a name="function_inet-ntoa"></a><p>
          <a class="indexterm" name="idm46444317392512"></a>

          <a class="link" href="functions.html#function_inet-ntoa"><code class="literal">INET_NTOA(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Given a numeric IPv4 network address in network byte order,
          returns the dotted-quad string representation of the address
          as a string in the connection character set.
          <a class="link" href="functions.html#function_inet-ntoa"><code class="literal">INET_NTOA()</code></a> returns
          <code class="literal">NULL</code> if it does not understand its
          argument.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT INET_NTOA(167773449);</code></strong>
        -&gt; '10.0.5.9'
</pre></li><li class="listitem"><a name="function_inet6-aton"></a><p>
          <a class="indexterm" name="idm46444317380960"></a>

          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Given an IPv6 or IPv4 network address as a string, returns a
          binary string that represents the numeric value of the address
          in network byte order (big endian). Because numeric-format
          IPv6 addresses require more bytes than the largest integer
          type, the representation returned by this function has the
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a> data type:
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY(16)</code></a> for IPv6
          addresses and <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY(4)</code></a> for
          IPv4 addresses. If the argument is not a valid address,
          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a> returns
          <code class="literal">NULL</code>.
        </p><p>
          The following examples use
          <a class="link" href="functions.html#function_hex"><code class="literal">HEX()</code></a> to display the
          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a> result in
          printable form:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(INET6_ATON('fdfe::5a55:caff:fefa:9089'));</code></strong>
        -&gt; 'FDFE0000000000005A55CAFFFEFA9089'
mysql&gt; <strong class="userinput"><code>SELECT HEX(INET6_ATON('10.0.5.9'));</code></strong>
        -&gt; '0A000509'
</pre><p>
          <code class="literal">INET6_ATON()</code> observes several constraints
          on valid arguments. These are given in the following list
          along with examples.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              A trailing zone ID is not permitted, as in
              <code class="literal">fe80::3%1</code> or
              <code class="literal">fe80::3%eth0</code>.
            </p></li><li class="listitem"><p>
              A trailing network mask is not permitted, as in
              <code class="literal">2001:45f:3:ba::/64</code> or
              <code class="literal">198.51.100.0/24</code>.
            </p></li><li class="listitem"><p>
              For values representing IPv4 addresses, only classless
              addresses are supported. Classful addresses such as
              <code class="literal">198.51.1</code> are rejected. A trailing port
              number is not permitted, as in
              <code class="literal">198.51.100.2:8080</code>. Hexadecimal numbers
              in address components are not permitted, as in
              <code class="literal">198.0xa0.1.2</code>. Octal numbers are not
              supported: <code class="literal">198.51.010.1</code> is treated as
              <code class="literal">198.51.10.1</code>, not
              <code class="literal">198.51.8.1</code>. These IPv4 constraints also
              apply to IPv6 addresses that have IPv4 address parts, such
              as IPv4-compatible or IPv4-mapped addresses.
</p></li></ul>
</div>
<p>
          To convert an IPv4 address <em class="replaceable"><code>expr</code></em>
          represented in numeric form as an
          <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">INT</code></a> value to an IPv6 address
          represented in numeric form as a
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY</code></a> value, use this
          expression:
        </p><pre data-lang="sql" class="programlisting">INET6_ATON(INET_NTOA(<em class="replaceable"><code>expr</code></em>))
</pre><p>
          For example:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(INET6_ATON(INET_NTOA(167773449)));</code></strong>
        -&gt; '0A000509'
</pre></li><li class="listitem"><a name="function_inet6-ntoa"></a><p>
          <a class="indexterm" name="idm46444317342976"></a>

          <a class="link" href="functions.html#function_inet6-ntoa"><code class="literal">INET6_NTOA(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Given an IPv6 or IPv4 network address represented in numeric
          form as a binary string, returns the string representation of
          the address as a string in the connection character set. If
          the argument is not a valid address,
          <a class="link" href="functions.html#function_inet6-ntoa"><code class="literal">INET6_NTOA()</code></a> returns
          <code class="literal">NULL</code>.
        </p><p>
          <a class="link" href="functions.html#function_inet6-ntoa"><code class="literal">INET6_NTOA()</code></a> has these
          properties:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              It does not use operating system functions to perform
              conversions, thus the output string is platform
              independent.
            </p></li><li class="listitem"><p>
              The return string has a maximum length of 39 (4 x 8 + 7).
              Given this statement:
            </p><pre data-lang="sql" class="programlisting">CREATE TABLE t AS SELECT INET6_NTOA(<em class="replaceable"><code>expr</code></em>) AS c1;
</pre><p>
              The resulting table would have this definition:
            </p><pre data-lang="sql" class="programlisting">CREATE TABLE t (c1 VARCHAR(39) CHARACTER SET utf8 DEFAULT NULL);</pre></li><li class="listitem"><p>
              The return string uses lowercase letters for IPv6
              addresses.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(INET6_ATON('fdfe::5a55:caff:fefa:9089'));</code></strong>
        -&gt; 'fdfe::5a55:caff:fefa:9089'
mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(INET6_ATON('10.0.5.9'));</code></strong>
        -&gt; '10.0.5.9'

mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(UNHEX('FDFE0000000000005A55CAFFFEFA9089'));</code></strong>
        -&gt; 'fdfe::5a55:caff:fefa:9089'
mysql&gt; <strong class="userinput"><code>SELECT INET6_NTOA(UNHEX('0A000509'));</code></strong>
        -&gt; '10.0.5.9'
</pre></li><li class="listitem"><a name="function_is-ipv4"></a><p>
          <a class="indexterm" name="idm46444317321184"></a>

          <a class="link" href="functions.html#function_is-ipv4"><code class="literal">IS_IPV4(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Returns 1 if the argument is a valid IPv4 address specified as
          a string, 0 otherwise.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT IS_IPV4('10.0.5.9'), IS_IPV4('10.0.5.256');</code></strong>
        -&gt; 1, 0
</pre><p>
          For a given argument, if
          <a class="link" href="functions.html#function_is-ipv4"><code class="literal">IS_IPV4()</code></a> returns 1,
          <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a> (and
          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a>) will return
          non-<code class="literal">NULL</code>. The converse statement is not
          true: In some cases,
          <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a> returns
          non-<code class="literal">NULL</code> when
          <a class="link" href="functions.html#function_is-ipv4"><code class="literal">IS_IPV4()</code></a> returns 0.
        </p><p>
          As implied by the preceding remarks,
          <a class="link" href="functions.html#function_is-ipv4"><code class="literal">IS_IPV4()</code></a> is more strict than
          <a class="link" href="functions.html#function_inet-aton"><code class="literal">INET_ATON()</code></a> about what
          constitutes a valid IPv4 address, so it may be useful for
          applications that need to perform strong checks against
          invalid values. Alternatively, use
          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a> to convert IPv4
          addresses to internal form and check for a
          <code class="literal">NULL</code> result (which indicates an invalid
          address). <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a> is
          equally strong as <a class="link" href="functions.html#function_is-ipv4"><code class="literal">IS_IPV4()</code></a>
          about checking IPv4 addresses.
        </p></li><li class="listitem"><a name="function_is-ipv4-compat"></a><p>
          <a class="indexterm" name="idm46444317295824"></a>

          <a class="link" href="functions.html#function_is-ipv4-compat"><code class="literal">IS_IPV4_COMPAT(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          This function takes an IPv6 address represented in numeric
          form as a binary string, as returned by
          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a>. It returns 1 if
          the argument is a valid IPv4-compatible IPv6 address, 0
          otherwise. IPv4-compatible addresses have the form
          <code class="literal">::<em class="replaceable"><code>ipv4_address</code></em></code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT IS_IPV4_COMPAT(INET6_ATON('::10.0.5.9'));</code></strong>
        -&gt; 1
mysql&gt; <strong class="userinput"><code>SELECT IS_IPV4_COMPAT(INET6_ATON('::ffff:10.0.5.9'));</code></strong>
        -&gt; 0
</pre><p>
          The IPv4 part of an IPv4-compatible address can also be
          represented using hexadecimal notation. For example,
          <code class="literal">198.51.100.1</code> has this raw hexadecimal
          value:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT HEX(INET6_ATON('198.51.100.1'));</code></strong>
        -&gt; 'C6336401'
</pre><p>
          Expressed in IPv4-compatible form,
          <code class="literal">::198.51.100.1</code> is equivalent to
          <code class="literal">::c0a8:0001</code> or (without leading zeros)
          <code class="literal">::c0a8:1</code>
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt; <strong class="userinput"><code>  IS_IPV4_COMPAT(INET6_ATON('::198.51.100.1')),</code></strong>
    -&gt; <strong class="userinput"><code>  IS_IPV4_COMPAT(INET6_ATON('::c0a8:0001')),</code></strong>
    -&gt; <strong class="userinput"><code>  IS_IPV4_COMPAT(INET6_ATON('::c0a8:1'));</code></strong>
        -&gt; 1, 1, 1
</pre></li><li class="listitem"><a name="function_is-ipv4-mapped"></a><p>
          <a class="indexterm" name="idm46444317273696"></a>

          <a class="link" href="functions.html#function_is-ipv4-mapped"><code class="literal">IS_IPV4_MAPPED(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          This function takes an IPv6 address represented in numeric
          form as a binary string, as returned by
          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a>. It returns 1 if
          the argument is a valid IPv4-mapped IPv6 address, 0 otherwise.
          IPv4-mapped addresses have the form
          <code class="literal">::ffff:<em class="replaceable"><code>ipv4_address</code></em></code>.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT IS_IPV4_MAPPED(INET6_ATON('::10.0.5.9'));</code></strong>
        -&gt; 0
mysql&gt; <strong class="userinput"><code>SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:10.0.5.9'));</code></strong>
        -&gt; 1
</pre><p>
          As with <code class="literal">IS_IPV4_COMPAT()</code> the IPv4 part of
          an IPv4-mapped address can also be represented using
          hexadecimal notation:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT</code></strong>
    -&gt; <strong class="userinput"><code>  IS_IPV4_MAPPED(INET6_ATON('::ffff:198.51.100.1')),</code></strong>
    -&gt; <strong class="userinput"><code>  IS_IPV4_MAPPED(INET6_ATON('::ffff:c0a8:0001')),</code></strong>
    -&gt; <strong class="userinput"><code>  IS_IPV4_MAPPED(INET6_ATON('::ffff:c0a8:1'));</code></strong>
        -&gt; 1, 1, 1
</pre></li><li class="listitem"><a name="function_is-ipv6"></a><p>
          <a class="indexterm" name="idm46444317255888"></a>

          <a class="link" href="functions.html#function_is-ipv6"><code class="literal">IS_IPV6(<em class="replaceable"><code>expr</code></em>)</code></a>
        </p><p>
          Returns 1 if the argument is a valid IPv6 address specified as
          a string, 0 otherwise. This function does not consider IPv4
          addresses to be valid IPv6 addresses.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT IS_IPV6('10.0.5.9'), IS_IPV6('::1');</code></strong>
        -&gt; 0, 1
</pre><p>
          For a given argument, if
          <a class="link" href="functions.html#function_is-ipv6"><code class="literal">IS_IPV6()</code></a> returns 1,
          <a class="link" href="functions.html#function_inet6-aton"><code class="literal">INET6_ATON()</code></a> will return
          non-<code class="literal">NULL</code>.
        </p></li><li class="listitem"><a name="function_is-uuid"></a><p>
          <a class="indexterm" name="idm46444317241920"></a>

          <a class="link" href="functions.html#function_is-uuid"><code class="literal">IS_UUID(<em class="replaceable"><code>string_uuid</code></em>)</code></a>
        </p><p>
          Returns 1 if the argument is a valid string-format UUID, 0 if
          the argument is not a valid UUID, and <code class="literal">NULL</code>
          if the argument is <code class="literal">NULL</code>.
        </p><p>
          <span class="quote">“<span class="quote">Valid</span>”</span> means that the value is in a format that
          can be parsed. That is, it has the correct length and contains
          only the permitted characters (hexadecimal digits in any
          lettercase and, optionally, dashes and curly braces). This
          format is most common:
        </p><pre data-lang="none" class="programlisting">aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</pre><p>
          These other formats are also permitted:
        </p><pre data-lang="none" class="programlisting">aaaaaaaabbbbccccddddeeeeeeeeeeee
{aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee}</pre><p>
          For the meanings of fields within the value, see the
          <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> function description.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT IS_UUID('6ccd780c-baba-1026-9564-5b8c656024db');</code></strong>
+-------------------------------------------------+
| IS_UUID('6ccd780c-baba-1026-9564-5b8c656024db') |
+-------------------------------------------------+
|                                               1 |
+-------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT IS_UUID('6CCD780C-BABA-1026-9564-5B8C656024DB');</code></strong>
+-------------------------------------------------+
| IS_UUID('6CCD780C-BABA-1026-9564-5B8C656024DB') |
+-------------------------------------------------+
|                                               1 |
+-------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT IS_UUID('6ccd780cbaba102695645b8c656024db');</code></strong>
+---------------------------------------------+
| IS_UUID('6ccd780cbaba102695645b8c656024db') |
+---------------------------------------------+
|                                           1 |
+---------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT IS_UUID('{6ccd780c-baba-1026-9564-5b8c656024db}');</code></strong>
+---------------------------------------------------+
| IS_UUID('{6ccd780c-baba-1026-9564-5b8c656024db}') |
+---------------------------------------------------+
|                                                 1 |
+---------------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT IS_UUID('6ccd780c-baba-1026-9564-5b8c6560');</code></strong>
+---------------------------------------------+
| IS_UUID('6ccd780c-baba-1026-9564-5b8c6560') |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT IS_UUID(RAND());</code></strong>
+-----------------+
| IS_UUID(RAND()) |
+-----------------+
|               0 |
+-----------------+
</pre></li><li class="listitem"><a name="function_master-pos-wait"></a><p>
          <a class="indexterm" name="idm46444317219744"></a>

          <a class="link" href="functions.html#function_master-pos-wait"><code class="literal">MASTER_POS_WAIT(<em class="replaceable"><code>log_name</code></em>,<em class="replaceable"><code>log_pos</code></em>[,<em class="replaceable"><code>timeout</code></em>][,<em class="replaceable"><code>channel</code></em>])</code></a>
        </p><p>
          This function is useful for control of master/slave
          synchronization. It blocks until the slave has read and
          applied all updates up to the specified position in the master
          log. The return value is the number of log events the slave
          had to wait for to advance to the specified position. The
          function returns <code class="literal">NULL</code> if the slave SQL
          thread is not started, the slave's master information is not
          initialized, the arguments are incorrect, or an error occurs.
          It returns <code class="literal">-1</code> if the timeout has been
          exceeded. If the slave SQL thread stops while
          <a class="link" href="functions.html#function_master-pos-wait"><code class="literal">MASTER_POS_WAIT()</code></a> is waiting,
          the function returns <code class="literal">NULL</code>. If the slave is
          past the specified position, the function returns immediately.
        </p><p>
          On a multithreaded slave, the function waits until expiry of
          the limit set by the
          <a class="link" href="replication.html#sysvar_slave_checkpoint_group"><code class="literal">slave_checkpoint_group</code></a> or
          <a class="link" href="replication.html#sysvar_slave_checkpoint_period"><code class="literal">slave_checkpoint_period</code></a>
          system variable, when the checkpoint operation is called to
          update the status of the slave. Depending on the setting for
          the system variables, the function might therefore return some
          time after the specified position was reached.
        </p><p>
          If binary log transaction compression is in use and the
          transaction payload at the specified position is compressed
          (as a <code class="literal">Transaction_payload_event</code>), the
          function waits until the whole transaction has been read and
          applied, and the positions have updated.
        </p><p>
          If a <em class="replaceable"><code>timeout</code></em> value is specified,
          <a class="link" href="functions.html#function_master-pos-wait"><code class="literal">MASTER_POS_WAIT()</code></a> stops waiting
          when <em class="replaceable"><code>timeout</code></em> seconds have elapsed.
          <em class="replaceable"><code>timeout</code></em> must be greater than 0; a
          zero or negative <em class="replaceable"><code>timeout</code></em> means no
          timeout.
        </p><p>
          The optional <em class="replaceable"><code>channel</code></em> value enables
          you to name which replication channel the function applies to.
          See <a class="xref" href="replication.html#replication-channels" title="17.2.3 Replication Channels">Section 17.2.3, “Replication Channels”</a> for more
          information.
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p></li><li class="listitem"><a name="function_name-const"></a><p>
          <a class="indexterm" name="idm46444317194608"></a>

          <a class="link" href="functions.html#function_name-const"><code class="literal">NAME_CONST(<em class="replaceable"><code>name</code></em>,<em class="replaceable"><code>value</code></em>)</code></a>
        </p><p>
          Returns the given value. When used to produce a result set
          column, <a class="link" href="functions.html#function_name-const"><code class="literal">NAME_CONST()</code></a> causes the
          column to have the given name. The arguments should be
          constants.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT NAME_CONST('myname', 14);</code></strong>
+--------+
| myname |
+--------+
|     14 |
+--------+
</pre><p>
          This function is for internal use only. The server uses it
          when writing statements from stored programs that contain
          references to local program variables, as described in
          <a class="xref" href="stored-objects.html#stored-programs-logging" title="24.7 Stored Program Binary Logging">Section 24.7, “Stored Program Binary Logging”</a>. You might see this
          function in the output from <a class="link" href="programs.html#mysqlbinlog" title="4.6.8 mysqlbinlog — Utility for Processing Binary Log Files"><span class="command"><strong>mysqlbinlog</strong></span></a>.
        </p><p>
          For your applications, you can obtain exactly the same result
          as in the example just shown by using simple aliasing, like
          this:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 14 AS myname;</code></strong>
+--------+
| myname |
+--------+
|     14 |
+--------+
1 row in set (0.00 sec)
</pre><p>
          See <a class="xref" href="sql-statements.html#select" title="13.2.10 SELECT Statement">Section 13.2.10, “SELECT Statement”</a>, for more information about
          column aliases.
        </p></li><li class="listitem"><a name="function_sleep"></a><p>
          <a class="indexterm" name="idm46444317177888"></a>

          <a class="link" href="functions.html#function_sleep"><code class="literal">SLEEP(<em class="replaceable"><code>duration</code></em>)</code></a>
        </p><p>
          Sleeps (pauses) for the number of seconds given by the
          <em class="replaceable"><code>duration</code></em> argument, then returns 0.
          The duration may have a fractional part. If the argument is
          <code class="literal">NULL</code> or negative,
          <a class="link" href="functions.html#function_sleep"><code class="literal">SLEEP()</code></a> produces a warning, or
          an error in strict SQL mode.
        </p><p>
          When sleep returns normally (without interruption), it returns
          0:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SLEEP(1000);</code></strong>
+-------------+
| SLEEP(1000) |
+-------------+
|           0 |
+-------------+
</pre><p>
          When <a class="link" href="functions.html#function_sleep"><code class="literal">SLEEP()</code></a> is the only thing
          invoked by a query that is interrupted, it returns 1 and the
          query itself returns no error. This is true whether the query
          is killed or times out:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              This statement is interrupted using
              <a class="link" href="sql-statements.html#kill" title="13.7.8.4 KILL Statement"><code class="literal">KILL QUERY</code></a>
              from another session:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT SLEEP(1000);</code></strong>
+-------------+
| SLEEP(1000) |
+-------------+
|           1 |
+-------------+
</pre></li><li class="listitem"><p>
              This statement is interrupted by timing out:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT /*+ MAX_EXECUTION_TIME(1) */ SLEEP(1000);</code></strong>
+-------------+
| SLEEP(1000) |
+-------------+
|           1 |
+-------------+
</pre></li></ul>
</div>
<p>
          When <a class="link" href="functions.html#function_sleep"><code class="literal">SLEEP()</code></a> is only part of a
          query that is interrupted, the query returns an error:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              This statement is interrupted using
              <a class="link" href="sql-statements.html#kill" title="13.7.8.4 KILL Statement"><code class="literal">KILL QUERY</code></a>
              from another session:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT 1 FROM t1 WHERE SLEEP(1000);</code></strong>
ERROR 1317 (70100): Query execution was interrupted
</pre></li><li class="listitem"><p>
              This statement is interrupted by timing out:
            </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT /*+ MAX_EXECUTION_TIME(1000) */ 1 FROM t1 WHERE SLEEP(1000);</code></strong>
ERROR 3024 (HY000): Query execution was interrupted, maximum statement
execution time exceeded
</pre></li></ul>
</div>
<p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p></li><li class="listitem"><a name="function_uuid"></a><p>
          <a class="indexterm" name="idm46444317146128"></a>

          <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a>
        </p><p>
          Returns a Universal Unique Identifier (UUID) generated
          according to RFC 4122, <span class="quote">“<span class="quote">A Universally Unique IDentifier
          (UUID) URN Namespace</span>”</span>
          (<a class="ulink" href="http://www.ietf.org/rfc/rfc4122.txt" target="_top">http://www.ietf.org/rfc/rfc4122.txt</a>).
        </p><p>
          A UUID is designed as a number that is globally unique in
          space and time. Two calls to
          <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> are expected to generate
          two different values, even if these calls are performed on two
          separate devices not connected to each other.
</p>
<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Warning
</div>
<p>
            Although <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> values are
            intended to be unique, they are not necessarily unguessable
            or unpredictable. If unpredictability is required, UUID
            values should be generated some other way.
</p>
</div>
<p>
          <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> returns a value that
          conforms to UUID version 1 as described in RFC 4122. The value
          is a 128-bit number represented as a <code class="literal">utf8</code>
          string of five hexadecimal numbers in
          <code class="literal">aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</code>
          format:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The first three numbers are generated from the low,
              middle, and high parts of a timestamp. The high part also
              includes the UUID version number.
            </p></li><li class="listitem"><p>
              The fourth number preserves temporal uniqueness in case
              the timestamp value loses monotonicity (for example, due
              to daylight saving time).
            </p></li><li class="listitem"><p>
              The fifth number is an IEEE 802 node number that provides
              spatial uniqueness. A random number is substituted if the
              latter is not available (for example, because the host
              device has no Ethernet card, or it is unknown how to find
              the hardware address of an interface on the host operating
              system). In this case, spatial uniqueness cannot be
              guaranteed. Nevertheless, a collision should have
              <span class="emphasis"><em>very</em></span> low probability.
            </p><p>
              The MAC address of an interface is taken into account only
              on FreeBSD, Linux, and Windows. On other operating
              systems, MySQL uses a randomly generated 48-bit number.
</p></li></ul>
</div>
<pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UUID();</code></strong>
        -&gt; '6ccd780c-baba-1026-9564-5b8c656024db'
</pre><p>
          To convert between string and binary UUID values, use the
          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a> and
          <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a> functions. To
          check whether a string is a valid UUID value, use the
          <a class="link" href="functions.html#function_is-uuid"><code class="literal">IS_UUID()</code></a> function.
        </p><p>
          This function is unsafe for statement-based replication. A
          warning is logged if you use this function when
          <a class="link" href="replication.html#sysvar_binlog_format"><code class="literal">binlog_format</code></a> is set to
          <code class="literal">STATEMENT</code>.
        </p></li><li class="listitem"><a name="function_uuid-short"></a><p>
          <a class="indexterm" name="idm46444317117040"></a>

          <a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a>
        </p><p>
          Returns a <span class="quote">“<span class="quote">short</span>”</span> universal identifier as a
          64-bit unsigned integer. Values returned by
          <a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a> differ from the
          string-format 128-bit identifiers returned by the
          <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> function and have
          different uniqueness properties. The value of
          <a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a> is guaranteed to
          be unique if the following conditions hold:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The <a class="link" href="replication.html#sysvar_server_id"><code class="literal">server_id</code></a> value of
              the current server is between 0 and 255 and is unique
              among your set of master and slave servers
            </p></li><li class="listitem"><p>
              You do not set back the system time for your server host
              between <a class="link" href="programs.html#mysqld" title="4.3.1 mysqld — The MySQL Server"><span class="command"><strong>mysqld</strong></span></a> restarts
            </p></li><li class="listitem"><p>
              You invoke <a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a> on
              average fewer than 16 million times per second between
              <a class="link" href="programs.html#mysqld" title="4.3.1 mysqld — The MySQL Server"><span class="command"><strong>mysqld</strong></span></a> restarts
</p></li></ul>
</div>
<p>
          The <a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a> return value
          is constructed this way:
        </p><pre data-lang="clike" class="programlisting">  (server_id &amp; 255) &lt;&lt; 56
+ (server_startup_time_in_seconds &lt;&lt; 24)
+ incremented_variable++;</pre><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT UUID_SHORT();</code></strong>
        -&gt; 92395783831158784
</pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Note
</div>
<p>
            <a class="link" href="functions.html#function_uuid-short"><code class="literal">UUID_SHORT()</code></a> does not work
            with statement-based replication.
</p>
</div>
</li><li class="listitem"><a name="function_uuid-to-bin"></a><p>
          <a class="indexterm" name="idm46444317090064"></a>

          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN(<em class="replaceable"><code>string_uuid</code></em>)</code></a>,
          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN(<em class="replaceable"><code>string_uuid</code></em>,
          <em class="replaceable"><code>swap_flag</code></em>)</code></a>
        </p><p>
          Converts a string UUID to a binary UUID and returns the
          result. (The <a class="link" href="functions.html#function_is-uuid"><code class="literal">IS_UUID()</code></a> function
          description lists the permitted string UUID formats.) The
          return binary UUID is a
          <a class="link" href="data-types.html#binary-varbinary" title="11.3.3 The BINARY and VARBINARY Types"><code class="literal">VARBINARY(16)</code></a> value. If the
          UUID argument is <code class="literal">NULL</code>, the return value is
          <code class="literal">NULL</code>. If any argument is invalid, an error
          occurs.
        </p><p>
          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a> takes one or two
          arguments:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
              The one-argument form takes a string UUID value. The
              binary result is in the same order as the string argument.
            </p></li><li class="listitem"><p>
              The two-argument form takes a string UUID value and a flag
              value:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: square; "><li class="listitem"><p>
                  If <em class="replaceable"><code>swap_flag</code></em> is 0, the
                  two-argument form is equivalent to the one-argument
                  form. The binary result is in the same order as the
                  string argument.
                </p></li><li class="listitem"><p>
                  If <em class="replaceable"><code>swap_flag</code></em> is 1, the
                  format of the return value differs: The time-low and
                  time-high parts (the first and third groups of
                  hexadecimal digits, respectively) are swapped. This
                  moves the more rapidly varying part to the right and
                  can improve indexing efficiency if the result is
                  stored in an indexed column.
</p></li></ul>
</div>
</li></ul>
</div>
<p>
          Time-part swapping assumes the use of UUID version 1 values,
          such as are generated by the
          <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> function. For UUID
          values produced by other means that do not follow version 1
          format, time-part swapping provides no benefit. For details
          about version 1 format, see the
          <a class="link" href="functions.html#function_uuid"><code class="literal">UUID()</code></a> function description.
        </p><p>
          Suppose that you have the following string UUID value:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET @uuid = '6ccd780c-baba-1026-9564-5b8c656024db';</code></strong>
</pre><p>
          To convert the string UUID to binary with or without time-part
          swapping, use <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a>:
        </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT HEX(UUID_TO_BIN(@uuid));</code></strong>
+----------------------------------+
| HEX(UUID_TO_BIN(@uuid))          |
+----------------------------------+
| 6CCD780CBABA102695645B8C656024DB |
+----------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT HEX(UUID_TO_BIN(@uuid, 0));</code></strong>
+----------------------------------+
| HEX(UUID_TO_BIN(@uuid, 0))       |
+----------------------------------+
| 6CCD780CBABA102695645B8C656024DB |
+----------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT HEX(UUID_TO_BIN(@uuid, 1));</code></strong>
+----------------------------------+
| HEX(UUID_TO_BIN(@uuid, 1))       |
+----------------------------------+
| 1026BABA6CCD780C95645B8C656024DB |
+----------------------------------+
</pre><p>
          To convert a binary UUID returned by
          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a> to a string UUID,
          use <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a>. If you
          produce a binary UUID by calling
          <a class="link" href="functions.html#function_uuid-to-bin"><code class="literal">UUID_TO_BIN()</code></a> with a second
          argument of 1 to swap time parts, you should also pass a
          second argument of 1 to
          <a class="link" href="functions.html#function_bin-to-uuid"><code class="literal">BIN_TO_UUID()</code></a> to unswap the
          time parts when converting the binary UUID back to a string
          UUID:
        </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid));</code></strong>
+--------------------------------------+
| BIN_TO_UUID(UUID_TO_BIN(@uuid))      |
+--------------------------------------+
| 6ccd780c-baba-1026-9564-5b8c656024db |
+--------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,0),0);</code></strong>
+--------------------------------------+
| BIN_TO_UUID(UUID_TO_BIN(@uuid,0),0)  |
+--------------------------------------+
| 6ccd780c-baba-1026-9564-5b8c656024db |
+--------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,1),1);</code></strong>
+--------------------------------------+
| BIN_TO_UUID(UUID_TO_BIN(@uuid,1),1)  |
+--------------------------------------+
| 6ccd780c-baba-1026-9564-5b8c656024db |
+--------------------------------------+
</pre><p>
          If the use of time-part swapping is not the same for the
          conversion in both directions, the original UUID will not be
          recovered properly:
        </p><pre data-lang="sql" class="programlisting">
mysql&gt; <strong class="userinput"><code>SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,0),1);</code></strong>
+--------------------------------------+
| BIN_TO_UUID(UUID_TO_BIN(@uuid,0),1)  |
+--------------------------------------+
| baba1026-780c-6ccd-9564-5b8c656024db |
+--------------------------------------+
mysql&gt; <strong class="userinput"><code>SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,1),0);</code></strong>
+--------------------------------------+
| BIN_TO_UUID(UUID_TO_BIN(@uuid,1),0)  |
+--------------------------------------+
| 1026baba-6ccd-780c-9564-5b8c656024db |
+--------------------------------------+
</pre></li><li class="listitem"><a name="function_values"></a><p>
          <a class="indexterm" name="idm46444317045696"></a>

          <a class="link" href="functions.html#function_values"><code class="literal">VALUES(<em class="replaceable"><code>col_name</code></em>)</code></a>
        </p><p>
          In an
          <a class="link" href="sql-statements.html#insert-on-duplicate" title="13.2.6.2 INSERT ... ON DUPLICATE KEY UPDATE Statement"><code class="literal">INSERT
          ... ON DUPLICATE KEY UPDATE</code></a> statement, you can use
          the
          <code class="literal">VALUES(<em class="replaceable"><code>col_name</code></em>)</code>
          function in the <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> clause
          to refer to column values from the
          <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> portion of the
          statement. In other words,
          <code class="literal">VALUES(<em class="replaceable"><code>col_name</code></em>)</code>
          in the <a class="link" href="sql-statements.html#update" title="13.2.13 UPDATE Statement"><code class="literal">UPDATE</code></a> clause refers to
          the value of <em class="replaceable"><code>col_name</code></em> that would be
          inserted, had no duplicate-key conflict occurred. This
          function is especially useful in multiple-row inserts. The
          <a class="link" href="functions.html#function_values"><code class="literal">VALUES()</code></a> function is meaningful
          only in the <code class="literal">ON DUPLICATE KEY UPDATE</code> clause
          of <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> statements and
          returns <code class="literal">NULL</code> otherwise.
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)</code></strong>
    -&gt; <strong class="userinput"><code>ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);</code></strong>
</pre>
<div class="important" style="margin-left: 0.5in; margin-right: 0.5in;">

<div class="admon-title">
Important
</div>
<p>
            This usage is deprecated in MySQL 8.0.20, and is subject to
            removal in a future release of MySQL. Use a row alias, or
            row and column aliases, instead. See
            <a class="xref" href="sql-statements.html#insert-on-duplicate" title="13.2.6.2 INSERT ... ON DUPLICATE KEY UPDATE Statement">Section 13.2.6.2, “INSERT ... ON DUPLICATE KEY UPDATE Statement”</a>, for more information
            and examples.
</p>
</div>
</li></ul>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="precision-math"></a>12.25 Precision Math</h2>

</div>

</div>

</div>
<div class="toc">
<dl class="toc"><dt><span class="section"><a href="functions.html#precision-math-numbers">12.25.1 Types of Numeric Values</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-decimal-characteristics">12.25.2 DECIMAL Data Type Characteristics</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-expressions">12.25.3 Expression Handling</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-rounding">12.25.4 Rounding Behavior</a></span></dt><dt><span class="section"><a href="functions.html#precision-math-examples">12.25.5 Precision Math Examples</a></span></dt></dl>
</div>
<a class="indexterm" name="idm46444317022784"></a><a class="indexterm" name="idm46444317021712"></a><a class="indexterm" name="idm46444317020640"></a><a class="indexterm" name="idm46444317019568"></a><a class="indexterm" name="idm46444317018496"></a><a class="indexterm" name="idm46444317017424"></a><a class="indexterm" name="idm46444317016352"></a><a class="indexterm" name="idm46444317014864"></a><a class="indexterm" name="idm46444317013376"></a><a class="indexterm" name="idm46444317012304"></a><a class="indexterm" name="idm46444317011216"></a><a class="indexterm" name="idm46444317010144"></a><p>
    MySQL provides support for precision math: numeric value handling
    that results in extremely accurate results and a high degree control
    over invalid values. Precision math is based on these two features:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
        SQL modes that control how strict the server is about accepting
        or rejecting invalid data.
      </p></li><li class="listitem"><p>
        The MySQL library for fixed-point arithmetic.
</p></li></ul>
</div>
<p>
    These features have several implications for numeric operations and
    provide a high degree of compliance with standard SQL:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
        <span class="bold"><strong>Precise calculations</strong></span>: For
        exact-value numbers, calculations do not introduce
        floating-point errors. Instead, exact precision is used. For
        example, MySQL treats a number such as <code class="literal">.0001</code>
        as an exact value rather than as an approximation, and summing
        it 10,000 times produces a result of exactly
        <code class="literal">1</code>, not a value that is merely
        <span class="quote">“<span class="quote">close</span>”</span> to 1.
      </p></li><li class="listitem"><p>
        <span class="bold"><strong>Well-defined rounding behavior</strong></span>:
        For exact-value numbers, the result of
        <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> depends on its argument,
        not on environmental factors such as how the underlying C
        library works.
      </p></li><li class="listitem"><p>
        <span class="bold"><strong>Platform independence</strong></span>:
        Operations on exact numeric values are the same across different
        platforms such as Windows and Unix.
      </p></li><li class="listitem"><p>
        <span class="bold"><strong>Control over handling of invalid
        values</strong></span>: Overflow and division by zero are detectable
        and can be treated as errors. For example, you can treat a value
        that is too large for a column as an error rather than having
        the value truncated to lie within the range of the column's data
        type. Similarly, you can treat division by zero as an error
        rather than as an operation that produces a result of
        <code class="literal">NULL</code>. The choice of which approach to take is
        determined by the setting of the server SQL mode.
</p></li></ul>
</div>
<p>
    The following discussion covers several aspects of how precision
    math works, including possible incompatibilities with older
    applications. At the end, some examples are given that demonstrate
    how MySQL handles numeric operations precisely. For information
    about controlling the SQL mode, see <a class="xref" href="server-administration.html#sql-mode" title="5.1.11 Server SQL Modes">Section 5.1.11, “Server SQL Modes”</a>.
</p>
<div class="section">

<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="precision-math-numbers"></a>12.25.1 Types of Numeric Values</h3>
</div>
</div>
</div>
<a class="indexterm" name="idm46444316990784"></a><a class="indexterm" name="idm46444316989696"></a><a class="indexterm" name="idm46444316988608"></a><a class="indexterm" name="idm46444316987120"></a><p>
      The scope of precision math for exact-value operations includes
      the exact-value data types (integer and
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> types) and exact-value
      numeric literals. Approximate-value data types and numeric
      literals are handled as floating-point numbers.
    </p><p>
      Exact-value numeric literals have an integer part or fractional
      part, or both. They may be signed. Examples: <code class="literal">1</code>,
      <code class="literal">.2</code>, <code class="literal">3.4</code>,
      <code class="literal">-5</code>, <code class="literal">-6.78</code>,
      <code class="literal">+9.10</code>.
    </p><p>
      Approximate-value numeric literals are represented in scientific
      notation with a mantissa and exponent. Either or both parts may be
      signed. Examples: <code class="literal">1.2E3</code>,
      <code class="literal">1.2E-3</code>, <code class="literal">-1.2E3</code>,
      <code class="literal">-1.2E-3</code>.
    </p><p>
      Two numbers that look similar may be treated differently. For
      example, <code class="literal">2.34</code> is an exact-value (fixed-point)
      number, whereas <code class="literal">2.34E0</code> is an approximate-value
      (floating-point) number.
    </p><p>
      The <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> data type is a
      fixed-point type and calculations are exact. In MySQL, the
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> type has several synonyms:
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">NUMERIC</code></a>,
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DEC</code></a>,
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">FIXED</code></a>. The integer types also are
      exact-value types.
    </p><p>
      The <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a> and
      <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a> data types are
      floating-point types and calculations are approximate. In MySQL,
      types that are synonymous with
      <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">FLOAT</code></a> or
      <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE</code></a> are
      <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">DOUBLE PRECISION</code></a> and
      <a class="link" href="data-types.html#floating-point-types" title="11.1.4 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE"><code class="literal">REAL</code></a>.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="precision-math-decimal-characteristics"></a>12.25.2 DECIMAL Data Type Characteristics</h3>

</div>

</div>

</div>
<p>
      This section discusses the characteristics of the
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> data type (and its
      synonyms), with particular regard to the following topics:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Maximum number of digits
        </p></li><li class="listitem"><p>
          Storage format
        </p></li><li class="listitem"><p>
          Storage requirements
        </p></li><li class="listitem"><p>
          The nonstandard MySQL extension to the upper range of
          <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> columns
</p></li></ul>
</div>
<p>
      The declaration syntax for a
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> column is
      <code class="literal">DECIMAL(<em class="replaceable"><code>M</code></em>,<em class="replaceable"><code>D</code></em>)</code>.
      The ranges of values for the arguments are as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          <em class="replaceable"><code>M</code></em> is the maximum number of digits
          (the precision). It has a range of 1 to 65.
        </p></li><li class="listitem"><p>
          <em class="replaceable"><code>D</code></em> is the number of digits to the
          right of the decimal point (the scale). It has a range of 0 to
          30 and must be no larger than <em class="replaceable"><code>M</code></em>.
</p></li></ul>
</div>
<p>
      If <em class="replaceable"><code>D</code></em> is omitted, the default is 0. If
      <em class="replaceable"><code>M</code></em> is omitted, the default is 10.
    </p><p>
      The maximum value of 65 for <em class="replaceable"><code>M</code></em> means
      that calculations on <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> values
      are accurate up to 65 digits. This limit of 65 digits of precision
      also applies to exact-value numeric literals, so the maximum range
      of such literals differs from before.
    </p><p>
      Values for <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> columns are
      stored using a binary format that packs nine decimal digits into 4
      bytes. The storage requirements for the integer and fractional
      parts of each value are determined separately. Each multiple of
      nine digits requires 4 bytes, and any remaining digits left over
      require some fraction of 4 bytes. The storage required for
      remaining digits is given by the following table.
</p>
<div class="informaltable">
<table summary="The number of bytes required for remaining/leftover digits in DECIMAL values."><col width="25%"><col width="25%"><thead><tr>
          <th scope="col">Leftover Digits</th>
          <th scope="col">Number of Bytes</th>
        </tr></thead><tbody><tr>
          <td scope="row">0</td>
          <td>0</td>
        </tr><tr>
          <td scope="row">1–2</td>
          <td>1</td>
        </tr><tr>
          <td scope="row">3–4</td>
          <td>2</td>
        </tr><tr>
          <td scope="row">5–6</td>
          <td>3</td>
        </tr><tr>
          <td scope="row">7–9</td>
          <td>4</td>
</tr></tbody></table>
</div>
<p>
      For example, a <code class="literal">DECIMAL(18,9)</code> column has nine
      digits on either side of the decimal point, so the integer part
      and the fractional part each require 4 bytes. A
      <code class="literal">DECIMAL(20,6)</code> column has fourteen integer
      digits and six fractional digits. The integer digits require four
      bytes for nine of the digits and 3 bytes for the remaining five
      digits. The six fractional digits require 3 bytes.
    </p><p>
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> columns do not store a
      leading <code class="literal">+</code> character or <code class="literal">-</code>
      character or leading <code class="literal">0</code> digits. If you insert
      <code class="literal">+0003.1</code> into a <code class="literal">DECIMAL(5,1)</code>
      column, it is stored as <code class="literal">3.1</code>. For negative
      numbers, a literal <code class="literal">-</code> character is not stored.
    </p><p>
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> columns do not permit
      values larger than the range implied by the column definition. For
      example, a <code class="literal">DECIMAL(3,0)</code> column supports a range
      of <code class="literal">-999</code> to <code class="literal">999</code>. A
      <code class="literal">DECIMAL(<em class="replaceable"><code>M</code></em>,<em class="replaceable"><code>D</code></em>)</code>
      column permits up to <em class="replaceable"><code>M</code></em> -
      <em class="replaceable"><code>D</code></em> digits to the left of the decimal
      point.
    </p><p>
      The SQL standard requires that the precision of
      <code class="literal">NUMERIC(<em class="replaceable"><code>M</code></em>,<em class="replaceable"><code>D</code></em>)</code>
      be <span class="emphasis"><em>exactly</em></span> <em class="replaceable"><code>M</code></em>
      digits. For
      <code class="literal">DECIMAL(<em class="replaceable"><code>M</code></em>,<em class="replaceable"><code>D</code></em>)</code>,
      the standard requires a precision of at least
      <em class="replaceable"><code>M</code></em> digits but permits more. In MySQL,
      <code class="literal">DECIMAL(<em class="replaceable"><code>M</code></em>,<em class="replaceable"><code>D</code></em>)</code>
      and
      <code class="literal">NUMERIC(<em class="replaceable"><code>M</code></em>,<em class="replaceable"><code>D</code></em>)</code>
      are the same, and both have a precision of exactly
      <em class="replaceable"><code>M</code></em> digits.
    </p><p>
      For a full explanation of the internal format of
      <code class="literal">DECIMAL</code> values, see the file
      <code class="filename">strings/decimal.c</code> in a MySQL source
      distribution. The format is explained (with an example) in the
      <code class="literal">decimal2bin()</code> function.
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="precision-math-expressions"></a>12.25.3 Expression Handling</h3>

</div>

</div>

</div>
<p>
      With precision math, exact-value numbers are used as given
      whenever possible. For example, numbers in comparisons are used
      exactly as given without a change in value. In strict SQL mode,
      for <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> into a column with an
      exact data type (<a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> or
      integer), a number is inserted with its exact value if it is
      within the column range. When retrieved, the value should be the
      same as what was inserted. (If strict SQL mode is not enabled,
      truncation for <a class="link" href="sql-statements.html#insert" title="13.2.6 INSERT Statement"><code class="literal">INSERT</code></a> is
      permissible.)
    </p><p>
      Handling of a numeric expression depends on what kind of values
      the expression contains:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If any approximate values are present, the expression is
          approximate and is evaluated using floating-point arithmetic.
        </p></li><li class="listitem"><p>
          If no approximate values are present, the expression contains
          only exact values. If any exact value contains a fractional
          part (a value following the decimal point), the expression is
          evaluated using <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> exact
          arithmetic and has a precision of 65 digits. The term
          <span class="quote">“<span class="quote">exact</span>”</span> is subject to the limits of what can be
          represented in binary. For example, <code class="literal">1.0/3.0</code>
          can be approximated in decimal notation as
          <code class="literal">.333...</code>, but not written as an exact
          number, so <code class="literal">(1.0/3.0)*3.0</code> does not evaluate
          to exactly <code class="literal">1.0</code>.
        </p></li><li class="listitem"><p>
          Otherwise, the expression contains only integer values. The
          expression is exact and is evaluated using integer arithmetic
          and has a precision the same as
          <a class="link" href="data-types.html#integer-types" title="11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"><code class="literal">BIGINT</code></a> (64 bits).
</p></li></ul>
</div>
<p>
      If a numeric expression contains any strings, they are converted
      to double-precision floating-point values and the expression is
      approximate.
    </p><p>
      Inserts into numeric columns are affected by the SQL mode, which
      is controlled by the <a class="link" href="server-administration.html#sysvar_sql_mode"><code class="literal">sql_mode</code></a>
      system variable. (See <a class="xref" href="server-administration.html#sql-mode" title="5.1.11 Server SQL Modes">Section 5.1.11, “Server SQL Modes”</a>.) The following
      discussion mentions strict mode (selected by the
      <a class="link" href="server-administration.html#sqlmode_strict_all_tables"><code class="literal">STRICT_ALL_TABLES</code></a> or
      <a class="link" href="server-administration.html#sqlmode_strict_trans_tables"><code class="literal">STRICT_TRANS_TABLES</code></a> mode values)
      and <a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a>.
      To turn on all restrictions, you can simply use
      <a class="link" href="server-administration.html#sqlmode_traditional"><code class="literal">TRADITIONAL</code></a> mode, which includes
      both strict mode values and
      <a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a>:
    </p><pre data-lang="sql" class="programlisting">SET sql_mode='TRADITIONAL';</pre><p>
      If a number is inserted into an exact type column
      (<a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> or integer), it is
      inserted with its exact value if it is within the column range and
      precision.
    </p><p>
      If the value has too many digits in the fractional part, rounding
      occurs and a note is generated. Rounding is done as described in
      <a class="xref" href="functions.html#precision-math-rounding" title="12.25.4 Rounding Behavior">Section 12.25.4, “Rounding Behavior”</a>. Truncation due to
      rounding of the fractional part is not an error, even in strict
      mode.
    </p><p>
      If the value has too many digits in the integer part, it is too
      large (out of range) and is handled as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If strict mode is not enabled, the value is truncated to the
          nearest legal value and a warning is generated.
        </p></li><li class="listitem"><p>
          If strict mode is enabled, an overflow error occurs.
</p></li></ul>
</div>
<p>
      Underflow is not detected, so underflow handling is undefined.
    </p><p>
      For inserts of strings into numeric columns, conversion from
      string to number is handled as follows if the string has
      nonnumeric contents:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          A string that does not begin with a number cannot be used as a
          number and produces an error in strict mode, or a warning
          otherwise. This includes the empty string.
        </p></li><li class="listitem"><p>
          A string that begins with a number can be converted, but the
          trailing nonnumeric portion is truncated. If the truncated
          portion contains anything other than spaces, this produces an
          error in strict mode, or a warning otherwise.
</p></li></ul>
</div>
<p>
      By default, division by zero produces a result of
      <code class="literal">NULL</code> and no warning. By setting the SQL mode
      appropriately, division by zero can be restricted.
    </p><p>
      With the
      <a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a> SQL
      mode enabled, MySQL handles division by zero differently:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          If strict mode is not enabled, a warning occurs.
        </p></li><li class="listitem"><p>
          If strict mode is enabled, inserts and updates involving
          division by zero are prohibited, and an error occurs.
</p></li></ul>
</div>
<p>
      In other words, inserts and updates involving expressions that
      perform division by zero can be treated as errors, but this
      requires
      <a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a> in
      addition to strict mode.
    </p><p>
      Suppose that we have this statement:
    </p><pre data-lang="sql" class="programlisting">INSERT INTO t SET i = 1/0;</pre><p>
      This is what happens for combinations of strict and
      <a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a>
      modes.
</p>
<div class="informaltable">
<table summary="What happens for combinations of strict and ERROR_FOR_DIVISION_BY_ZERO modes."><col width="50%"><col width="50%"><thead><tr>
          <th scope="col"><a class="link" href="server-administration.html#sysvar_sql_mode"><code class="literal">sql_mode</code></a> Value</th>
          <th scope="col">Result</th>
        </tr></thead><tbody><tr>
          <td scope="row"><code class="literal">''</code> (Default)</td>
          <td>No warning, no error; <code class="literal">i</code> is set to
            <code class="literal">NULL</code>.</td>
        </tr><tr>
          <td scope="row">strict</td>
          <td>No warning, no error; <code class="literal">i</code> is set to
            <code class="literal">NULL</code>.</td>
        </tr><tr>
          <td scope="row"><a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a></td>
          <td>Warning, no error; <code class="literal">i</code> is set to
            <code class="literal">NULL</code>.</td>
        </tr><tr>
          <td scope="row">strict,<a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a></td>
          <td>Error condition; no row is inserted.</td>
</tr></tbody></table>
</div>

</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="precision-math-rounding"></a>12.25.4 Rounding Behavior</h3>

</div>

</div>

</div>
<p>
      This section discusses precision math rounding for the
      <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> function and for inserts
      into columns with exact-value types
      (<a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> and integer).
    </p><p>
      The <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> function rounds
      differently depending on whether its argument is exact or
      approximate:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          For exact-value numbers,
          <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> uses the <span class="quote">“<span class="quote">round
          half up</span>”</span> rule: A value with a fractional part of .5 or
          greater is rounded up to the next integer if positive or down
          to the next integer if negative. (In other words, it is
          rounded away from zero.) A value with a fractional part less
          than .5 is rounded down to the next integer if positive or up
          to the next integer if negative. (In other words, it is
          rounded toward zero.)
        </p></li><li class="listitem"><p>
          For approximate-value numbers, the result depends on the C
          library. On many systems, this means that
          <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> uses the <span class="quote">“<span class="quote">round
          to nearest even</span>”</span> rule: A value with a fractional part
          exactly half way between two integers is rounded to the
          nearest even integer.
</p></li></ul>
</div>
<p>
      The following example shows how rounding differs for exact and
      approximate values:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ROUND(2.5), ROUND(25E-1);</code></strong>
+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
| 3          |            2 |
+------------+--------------+
</pre><p>
      For inserts into a <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> or
      integer column, the target is an exact data type, so rounding uses
      <span class="quote">“<span class="quote">round half away from zero,</span>”</span> regardless of whether
      the value to be inserted is exact or approximate:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE t (d DECIMAL(10,0));</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES(2.5),(2.5E0);</code></strong>
Query OK, 2 rows affected, 2 warnings (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 2

mysql&gt; <strong class="userinput"><code>SHOW WARNINGS;</code></strong>
+-------+------+----------------------------------------+
| Level | Code | Message                                |
+-------+------+----------------------------------------+
| Note  | 1265 | Data truncated for column 'd' at row 1 |
| Note  | 1265 | Data truncated for column 'd' at row 2 |
+-------+------+----------------------------------------+
2 rows in set (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT d FROM t;</code></strong>
+------+
| d    |
+------+
|    3 |
|    3 |
+------+
2 rows in set (0.00 sec)
</pre><p>
      The <a class="link" href="sql-statements.html#show-warnings" title="13.7.7.40 SHOW WARNINGS Statement"><code class="literal">SHOW WARNINGS</code></a> statement
      displays the notes that are generated by truncation due to
      rounding of the fractional part. Such truncation is not an error,
      even in strict SQL mode (see
      <a class="xref" href="functions.html#precision-math-expressions" title="12.25.3 Expression Handling">Section 12.25.3, “Expression Handling”</a>).
</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="precision-math-examples"></a>12.25.5 Precision Math Examples</h3>

</div>

</div>

</div>
<p>
      This section provides some examples that show precision math query
      results in MySQL. These examples demonstrate the principles
      described in <a class="xref" href="functions.html#precision-math-expressions" title="12.25.3 Expression Handling">Section 12.25.3, “Expression Handling”</a>, and
      <a class="xref" href="functions.html#precision-math-rounding" title="12.25.4 Rounding Behavior">Section 12.25.4, “Rounding Behavior”</a>.
    </p><p>
      <span class="bold"><strong>Example 1</strong></span>. Numbers are used with
      their exact value as given when possible:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT (.1 + .2) = .3;</code></strong>
+----------------+
| (.1 + .2) = .3 |
+----------------+
|              1 |
+----------------+
</pre><p>
      For floating-point values, results are inexact:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT (.1E0 + .2E0) = .3E0;</code></strong>
+----------------------+
| (.1E0 + .2E0) = .3E0 |
+----------------------+
|                    0 |
+----------------------+
</pre><p>
      Another way to see the difference in exact and approximate value
      handling is to add a small number to a sum many times. Consider
      the following stored procedure, which adds
      <code class="literal">.0001</code> to a variable 1,000 times.
    </p><pre data-lang="sql" class="programlisting">CREATE PROCEDURE p ()
BEGIN
  DECLARE i INT DEFAULT 0;
  DECLARE d DECIMAL(10,4) DEFAULT 0;
  DECLARE f FLOAT DEFAULT 0;
  WHILE i &lt; 10000 DO
    SET d = d + .0001;
    SET f = f + .0001E0;
    SET i = i + 1;
  END WHILE;
  SELECT d, f;
END;</pre><p>
      The sum for both <code class="literal">d</code> and <code class="literal">f</code>
      logically should be 1, but that is true only for the decimal
      calculation. The floating-point calculation introduces small
      errors:
    </p><pre data-lang="none" class="programlisting">+--------+------------------+
| d      | f                |
+--------+------------------+
| 1.0000 | 0.99999999999991 |
+--------+------------------+</pre><p>
      <span class="bold"><strong>Example 2</strong></span>. Multiplication is
      performed with the scale required by standard SQL. That is, for
      two numbers <em class="replaceable"><code>X1</code></em> and
      <em class="replaceable"><code>X2</code></em> that have scale
      <em class="replaceable"><code>S1</code></em> and <em class="replaceable"><code>S2</code></em>,
      the scale of the result is <code class="literal"><em class="replaceable"><code>S1</code></em>
      + <em class="replaceable"><code>S2</code></em></code>:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT .01 * .01;</code></strong>
+-----------+
| .01 * .01 |
+-----------+
| 0.0001    |
+-----------+
</pre><p>
      <span class="bold"><strong>Example 3</strong></span>. Rounding behavior for
      exact-value numbers is well-defined:
    </p><p>
      Rounding behavior (for example, with the
      <a class="link" href="functions.html#function_round"><code class="literal">ROUND()</code></a> function) is independent of
      the implementation of the underlying C library, which means that
      results are consistent from platform to platform.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
          Rounding for exact-value columns
          (<a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a> and integer) and
          exact-valued numbers uses the <span class="quote">“<span class="quote">round half away from
          zero</span>”</span> rule. A value with a fractional part of .5 or
          greater is rounded away from zero to the nearest integer, as
          shown here:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ROUND(2.5), ROUND(-2.5);</code></strong>
+------------+-------------+
| ROUND(2.5) | ROUND(-2.5) |
+------------+-------------+
| 3          | -3          |
+------------+-------------+
</pre></li><li class="listitem"><p>
          Rounding for floating-point values uses the C library, which
          on many systems uses the <span class="quote">“<span class="quote">round to nearest even</span>”</span>
          rule. A value with a fractional part exactly half way between
          two integers is rounded to the nearest even integer:
        </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SELECT ROUND(2.5E0), ROUND(-2.5E0);</code></strong>
+--------------+---------------+
| ROUND(2.5E0) | ROUND(-2.5E0) |
+--------------+---------------+
|            2 |            -2 |
+--------------+---------------+
</pre></li></ul>
</div>
<p>
      <span class="bold"><strong>Example 4</strong></span>. In strict mode,
      inserting a value that is out of range for a column causes an
      error, rather than truncation to a legal value.
    </p><p>
      When MySQL is not running in strict mode, truncation to a legal
      value occurs:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET sql_mode='';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>CREATE TABLE t (i TINYINT);</code></strong>
Query OK, 0 rows affected (0.01 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t SET i = 128;</code></strong>
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT i FROM t;</code></strong>
+------+
| i    |
+------+
|  127 |
+------+
1 row in set (0.00 sec)
</pre><p>
      However, an error occurs if strict mode is in effect:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET sql_mode='STRICT_ALL_TABLES';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>CREATE TABLE t (i TINYINT);</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t SET i = 128;</code></strong>
ERROR 1264 (22003): Out of range value adjusted for column 'i' at row 1

mysql&gt; <strong class="userinput"><code>SELECT i FROM t;</code></strong>
Empty set (0.00 sec)
</pre><p>
      <span class="bold"><strong>Example 5</strong></span>: In strict mode and
      with <a class="link" href="server-administration.html#sqlmode_error_for_division_by_zero"><code class="literal">ERROR_FOR_DIVISION_BY_ZERO</code></a>
      set, division by zero causes an error, not a result of
      <code class="literal">NULL</code>.
    </p><p>
      In nonstrict mode, division by zero has a result of
      <code class="literal">NULL</code>:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET sql_mode='';</code></strong>
Query OK, 0 rows affected (0.01 sec)

mysql&gt; <strong class="userinput"><code>CREATE TABLE t (i TINYINT);</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t SET i = 1 / 0;</code></strong>
Query OK, 1 row affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>SELECT i FROM t;</code></strong>
+------+
| i    |
+------+
| NULL |
+------+
1 row in set (0.03 sec)
</pre><p>
      However, division by zero is an error if the proper SQL modes are
      in effect:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>CREATE TABLE t (i TINYINT);</code></strong>
Query OK, 0 rows affected (0.00 sec)

mysql&gt; <strong class="userinput"><code>INSERT INTO t SET i = 1 / 0;</code></strong>
ERROR 1365 (22012): Division by 0

mysql&gt; <strong class="userinput"><code>SELECT i FROM t;</code></strong>
Empty set (0.01 sec)
</pre><p>
      <span class="bold"><strong>Example 6</strong></span>. Exact-value literals
      are evaluated as exact values.
    </p><p>
      Approximate-value literals are evaluated using floating point, but
      exact-value literals are handled as
      <a class="link" href="data-types.html#fixed-point-types" title="11.1.3 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC"><code class="literal">DECIMAL</code></a>:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;</code></strong>
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql&gt; <strong class="userinput"><code>DESCRIBE t;</code></strong>
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| a     | decimal(2,1) unsigned | NO   |     | 0.0     |       |
| b     | double                | NO   |     | 0       |       |
+-------+-----------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
</pre><p>
      <span class="bold"><strong>Example 7</strong></span>. If the argument to an
      aggregate function is an exact numeric type, the result is also an
      exact numeric type, with a scale at least that of the argument.
    </p><p>
      Consider these statements:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>CREATE TABLE t (i INT, d DECIMAL, f FLOAT);</code></strong>
mysql&gt; <strong class="userinput"><code>INSERT INTO t VALUES(1,1,1);</code></strong>
mysql&gt; <strong class="userinput"><code>CREATE TABLE y SELECT AVG(i), AVG(d), AVG(f) FROM t;</code></strong>
</pre><p>
      The result is a double only for the floating-point argument. For
      exact type arguments, the result is also an exact type:
    </p><pre data-lang="sql" class="programlisting">mysql&gt; <strong class="userinput"><code>DESCRIBE y;</code></strong>
+--------+---------------+------+-----+---------+-------+
| Field  | Type          | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| AVG(i) | decimal(14,4) | YES  |     | NULL    |       |
| AVG(d) | decimal(14,4) | YES  |     | NULL    |       |
| AVG(f) | double        | YES  |     | NULL    |       |
+--------+---------------+------+-----+---------+-------+
</pre><p>
      The result is a double only for the floating-point argument. For
      exact type arguments, the result is also an exact type.
</p>
</div>

</div>

</div>
<div class="copyright-footer">

</div>
<div class="navfooter">
<hr>
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="data-types.html">Prev</a></td>
<td width="20%" align="center"><a accesskey="u" href="">Up</a></td>
<td width="40%" align="right"> <a accesskey="n" href="sql-statements.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Chapter 11 Data Types</td>
<td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td>
<td width="40%" align="right" valign="top">Chapter 13 SQL Statements</td>
</tr>
</table>
</div>
</body>
</html>
